tinkerforge-async 1.5.3__tar.gz → 1.6.0__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.
- {tinkerforge_async-1.5.3/tinkerforge_async.egg-info → tinkerforge_async-1.6.0}/PKG-INFO +8 -8
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/README.md +5 -4
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/pyproject.toml +0 -2
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/_version.py +1 -1
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/async_event_bus.py +2 -2
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/brick_master.py +7 -7
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_ambient_light_v2.py +1 -1
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_ambient_light_v3.py +2 -2
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_analog_in.py +1 -1
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_barometer.py +1 -1
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_barometer_v2.py +4 -4
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_humidity.py +1 -1
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_humidity_v2.py +3 -3
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_industrial_dual_analog_in_v2.py +6 -4
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_io16.py +10 -10
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_io4_v2.py +177 -25
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_moisture.py +1 -1
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_ptc.py +1 -1
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_ptc_v2.py +3 -3
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_rs232_v2.py +1 -1
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_segment_display_4x7.py +1 -1
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_segment_display_4x7_v2.py +1 -1
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_temperature.py +1 -1
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_temperature_v2.py +2 -2
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_thermocouple_v2.py +2 -2
- tinkerforge_async-1.6.0/tinkerforge_async/helper.py +42 -0
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0/tinkerforge_async.egg-info}/PKG-INFO +8 -8
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async.egg-info/SOURCES.txt +1 -0
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/LICENSE +0 -0
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/setup.cfg +0 -0
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/setup.py +0 -0
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/__init__.py +0 -0
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_industrial_ptc.py +0 -0
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_isolator.py +0 -0
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_motion_detector_v2.py +0 -0
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/device_factory.py +0 -0
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/devices.py +0 -0
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/ip_connection.py +0 -0
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/ip_connection_helper.py +0 -0
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async.egg-info/dependency_links.txt +0 -0
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async.egg-info/requires.txt +0 -0
- {tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: tinkerforge-async
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.6.0
|
4
4
|
Summary: Python3 AsyncIO Tinkerforge driver
|
5
5
|
Author-email: Patrick Baus <patrick.baus@physik.tu-darmstadt.de>
|
6
6
|
License: GNU General Public License v3 (GPLv3)
|
@@ -9,8 +9,6 @@ Project-URL: Bug Tracker, https://github.com/PatrickBaus/tinkerforge_async/issue
|
|
9
9
|
Project-URL: Download, https://github.com/PatrickBaus/tinkerforge_async/releases
|
10
10
|
Keywords: IoT,Tinkerforge,API
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
12
|
-
Classifier: Programming Language :: Python :: 3.7
|
13
|
-
Classifier: Programming Language :: Python :: 3.8
|
14
12
|
Classifier: Programming Language :: Python :: 3.9
|
15
13
|
Classifier: Programming Language :: Python :: 3.10
|
16
14
|
Classifier: Programming Language :: Python :: 3.11
|
@@ -44,6 +42,7 @@ Requires-Dist: mypy; extra == "test"
|
|
44
42
|
Requires-Dist: pylint; extra == "test"
|
45
43
|
Requires-Dist: pytest; extra == "test"
|
46
44
|
Requires-Dist: setuptools; extra == "test"
|
45
|
+
Dynamic: license-file
|
47
46
|
|
48
47
|
[](../../actions/workflows/pylint.yml)
|
49
48
|
[](https://pypi.org/project/tinkerforge-async/)
|
@@ -106,7 +105,7 @@ pip install tinkerforge-async
|
|
106
105
|
# Changes made to the API
|
107
106
|
Some design choices of the original Tinkerforge API are overly complex. I therefore replaced them with a simpler and more intuitive approach. A list of things that were changed can be found below:
|
108
107
|
## Design Changes
|
109
|
-
- Only Python 3 is supported (3.
|
108
|
+
- Only Python 3 is supported (3.9+)
|
110
109
|
- Replaced threads with an async event loop
|
111
110
|
- Completely rewritten how responses from bricks/bricklets work. All setters now have a `response_expected` parameter, which is set to `True` by default. If there is an error when calling the function, it will then raise an exception - either an `AttributeError` if the function is unknown, or a `ValueError` if one or more parameters are invalid.
|
112
111
|
|
@@ -188,9 +187,11 @@ Some design choices of the original Tinkerforge API are overly complex. I theref
|
|
188
187
|
- `IPConnection.register_callback(callback_id, function)`: Replaced by `register_event_queue()`
|
189
188
|
- `IPConnection.connect(host, port=4223, authentication_secret='')`: If `authentication_secret` is not empty, try to authenticate.
|
190
189
|
|
191
|
-
- ### [
|
190
|
+
- ### [IO-4 Bricklet 2.0](https://www.tinkerforge.com/de/doc/Software/Bricklets/IO4V2_Bricklet_Python.html)
|
192
191
|
- `BrickletIO4V2.set_pwm_configuration()` will now take the frequency in units of Hz and the duty cycle is normalized to 1, so it will take a float from [0...1].
|
193
|
-
- `BrickletIO4V2.get_pwm_configuration()` will return the frequency in units of
|
192
|
+
- `BrickletIO4V2.get_pwm_configuration()` will return the frequency in units of Hz and the duty cycle is normalized to 1.
|
193
|
+
- `BrickletIO4V2.set_edge_count_callback_configuration()` sets the callback configuration for the edge counter callback. Its secondary ids are in [5...8] for channels [0...3].
|
194
|
+
- `BrickletIO4V2.get_edge_count_callback_configuration()` returns the callback configuration for the edge counter callback.
|
194
195
|
|
195
196
|
- ### [Master Brick](https://www.tinkerforge.com/en/doc/Software/Bricks/Master_Brick_Python.html)
|
196
197
|
- `BrickMaster.set_wifi_configuration()`/`BrickMaster.get_wifi_configuration()` will take/return all ips in natural order
|
@@ -210,7 +211,6 @@ Some design choices of the original Tinkerforge API are overly complex. I theref
|
|
210
211
|
- `BrickletThermocoupleV2()` takes an additional parameter to define the type of sensor. The options are of type `BrickletThermocoupleV2.SensorType`. The default is `BrickletPtc.SensorType.TYPE_K`.
|
211
212
|
- `BrickletThermocoupleV2.sensor_type` getter and setter to change the type of sensor used.
|
212
213
|
|
213
|
-
|
214
214
|
- ### [Segment Display 4x7 Bricklet 2.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Segment_Display_4x7_V2.html)
|
215
215
|
- `BrickletSegmentDisplay4x7V2.set_segments()` takes a `list`/`tuple` of 4 `int` instead of digit0, digit1, digit2, digit3. This is the same API as the older [Segment Display 4x7 Bricklet](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Segment_Display_4x7.html).
|
216
216
|
|
@@ -59,7 +59,7 @@ pip install tinkerforge-async
|
|
59
59
|
# Changes made to the API
|
60
60
|
Some design choices of the original Tinkerforge API are overly complex. I therefore replaced them with a simpler and more intuitive approach. A list of things that were changed can be found below:
|
61
61
|
## Design Changes
|
62
|
-
- Only Python 3 is supported (3.
|
62
|
+
- Only Python 3 is supported (3.9+)
|
63
63
|
- Replaced threads with an async event loop
|
64
64
|
- Completely rewritten how responses from bricks/bricklets work. All setters now have a `response_expected` parameter, which is set to `True` by default. If there is an error when calling the function, it will then raise an exception - either an `AttributeError` if the function is unknown, or a `ValueError` if one or more parameters are invalid.
|
65
65
|
|
@@ -141,9 +141,11 @@ Some design choices of the original Tinkerforge API are overly complex. I theref
|
|
141
141
|
- `IPConnection.register_callback(callback_id, function)`: Replaced by `register_event_queue()`
|
142
142
|
- `IPConnection.connect(host, port=4223, authentication_secret='')`: If `authentication_secret` is not empty, try to authenticate.
|
143
143
|
|
144
|
-
- ### [
|
144
|
+
- ### [IO-4 Bricklet 2.0](https://www.tinkerforge.com/de/doc/Software/Bricklets/IO4V2_Bricklet_Python.html)
|
145
145
|
- `BrickletIO4V2.set_pwm_configuration()` will now take the frequency in units of Hz and the duty cycle is normalized to 1, so it will take a float from [0...1].
|
146
|
-
- `BrickletIO4V2.get_pwm_configuration()` will return the frequency in units of
|
146
|
+
- `BrickletIO4V2.get_pwm_configuration()` will return the frequency in units of Hz and the duty cycle is normalized to 1.
|
147
|
+
- `BrickletIO4V2.set_edge_count_callback_configuration()` sets the callback configuration for the edge counter callback. Its secondary ids are in [5...8] for channels [0...3].
|
148
|
+
- `BrickletIO4V2.get_edge_count_callback_configuration()` returns the callback configuration for the edge counter callback.
|
147
149
|
|
148
150
|
- ### [Master Brick](https://www.tinkerforge.com/en/doc/Software/Bricks/Master_Brick_Python.html)
|
149
151
|
- `BrickMaster.set_wifi_configuration()`/`BrickMaster.get_wifi_configuration()` will take/return all ips in natural order
|
@@ -163,7 +165,6 @@ Some design choices of the original Tinkerforge API are overly complex. I theref
|
|
163
165
|
- `BrickletThermocoupleV2()` takes an additional parameter to define the type of sensor. The options are of type `BrickletThermocoupleV2.SensorType`. The default is `BrickletPtc.SensorType.TYPE_K`.
|
164
166
|
- `BrickletThermocoupleV2.sensor_type` getter and setter to change the type of sensor used.
|
165
167
|
|
166
|
-
|
167
168
|
- ### [Segment Display 4x7 Bricklet 2.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Segment_Display_4x7_V2.html)
|
168
169
|
- `BrickletSegmentDisplay4x7V2.set_segments()` takes a `list`/`tuple` of 4 `int` instead of digit0, digit1, digit2, digit3. This is the same API as the older [Segment Display 4x7 Bricklet](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Segment_Display_4x7.html).
|
169
170
|
|
@@ -9,8 +9,6 @@ license = { text="GNU General Public License v3 (GPLv3)" }
|
|
9
9
|
requires-python = ">=3.7"
|
10
10
|
classifiers = [
|
11
11
|
"Programming Language :: Python :: 3",
|
12
|
-
"Programming Language :: Python :: 3.7",
|
13
|
-
"Programming Language :: Python :: 3.8",
|
14
12
|
"Programming Language :: Python :: 3.9",
|
15
13
|
"Programming Language :: Python :: 3.10",
|
16
14
|
"Programming Language :: Python :: 3.11",
|
@@ -1,2 +1,2 @@
|
|
1
1
|
# pylint: disable=missing-module-docstring
|
2
|
-
__version__ = "1.
|
2
|
+
__version__ = "1.6.0"
|
@@ -9,7 +9,7 @@ from typing import Any, AsyncGenerator
|
|
9
9
|
|
10
10
|
class EventBus:
|
11
11
|
"""
|
12
|
-
An event bus
|
12
|
+
An event bus that is using the async generator syntax for distributing events.
|
13
13
|
It uses dicts and sets internally to ensure good performance.
|
14
14
|
"""
|
15
15
|
|
@@ -18,7 +18,7 @@ class EventBus:
|
|
18
18
|
|
19
19
|
async def register(self, event_name: str) -> AsyncGenerator[Any, None]:
|
20
20
|
"""
|
21
|
-
The async generator
|
21
|
+
The async generator that yields events subscribed to `event_name`.
|
22
22
|
|
23
23
|
Parameters
|
24
24
|
----------
|
@@ -1252,7 +1252,7 @@ class BrickMaster(DeviceWithMCU): # pylint: disable=too-many-public-methods
|
|
1252
1252
|
)
|
1253
1253
|
return unpack_payload(payload, "!")
|
1254
1254
|
|
1255
|
-
async def set_wifi_configuration( # pylint: disable=too-many-arguments
|
1255
|
+
async def set_wifi_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
1256
1256
|
self,
|
1257
1257
|
ssid: str | bytes,
|
1258
1258
|
connection: _WifiConnection | int,
|
@@ -1334,7 +1334,7 @@ class BrickMaster(DeviceWithMCU): # pylint: disable=too-many-public-methods
|
|
1334
1334
|
ssid, WifiConnection(connection), ip_addr[::-1], subnet_mask[::-1], gateway[::-1], port
|
1335
1335
|
)
|
1336
1336
|
|
1337
|
-
async def set_wifi_encryption( # pylint: disable=too-many-arguments
|
1337
|
+
async def set_wifi_encryption( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
1338
1338
|
self,
|
1339
1339
|
encryption: WifiEncryptionMode,
|
1340
1340
|
key_index: int = 1,
|
@@ -2084,7 +2084,7 @@ class BrickMaster(DeviceWithMCU): # pylint: disable=too-many-public-methods
|
|
2084
2084
|
|
2085
2085
|
return unpack_payload(payload, "!")
|
2086
2086
|
|
2087
|
-
async def set_ethernet_configuration( # pylint: disable=too-many-arguments
|
2087
|
+
async def set_ethernet_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
2088
2088
|
self,
|
2089
2089
|
connection: _EthernetConnection,
|
2090
2090
|
ip_address: tuple[int, int, int, int] = (0, 0, 0, 0),
|
@@ -2510,7 +2510,7 @@ class BrickMaster(DeviceWithMCU): # pylint: disable=too-many-public-methods
|
|
2510
2510
|
|
2511
2511
|
return unpack_payload(payload, "64s")
|
2512
2512
|
|
2513
|
-
async def set_wifi2_configuration( # pylint: disable=too-many-arguments
|
2513
|
+
async def set_wifi2_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
2514
2514
|
self,
|
2515
2515
|
port: int = 4223,
|
2516
2516
|
websocket_port: int = 4280,
|
@@ -2636,7 +2636,7 @@ class BrickMaster(DeviceWithMCU): # pylint: disable=too-many-public-methods
|
|
2636
2636
|
ap_connected_count,
|
2637
2637
|
)
|
2638
2638
|
|
2639
|
-
async def set_wifi2_client_configuration( # pylint: disable=too-many-arguments
|
2639
|
+
async def set_wifi2_client_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
2640
2640
|
self,
|
2641
2641
|
enable: bool = True,
|
2642
2642
|
ssid: bytes | str = "tinkerforge",
|
@@ -2809,7 +2809,7 @@ class BrickMaster(DeviceWithMCU): # pylint: disable=too-many-public-methods
|
|
2809
2809
|
)
|
2810
2810
|
return unpack_payload(payload, "64s")
|
2811
2811
|
|
2812
|
-
async def set_wifi2_ap_configuration( # pylint: disable=too-many-arguments
|
2812
|
+
async def set_wifi2_ap_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
2813
2813
|
self,
|
2814
2814
|
enable: bool = True,
|
2815
2815
|
ssid: bytes | str = "WIFI Extension 2.0 Access Point",
|
@@ -3026,7 +3026,7 @@ class BrickMaster(DeviceWithMCU): # pylint: disable=too-many-public-methods
|
|
3026
3026
|
)
|
3027
3027
|
return unpack_payload(payload, "!")
|
3028
3028
|
|
3029
|
-
async def set_wifi2_mesh_configuration( # pylint: disable=too-many-arguments
|
3029
|
+
async def set_wifi2_mesh_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
3030
3030
|
self,
|
3031
3031
|
enable: bool = False,
|
3032
3032
|
root_ip: tuple[int, int, int, int] = (0, 0, 0, 0),
|
{tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_ambient_light_v2.py
RENAMED
@@ -131,7 +131,7 @@ class BrickletAmbientLightV2(Device):
|
|
131
131
|
|
132
132
|
return await self.get_illuminance()
|
133
133
|
|
134
|
-
async def set_callback_configuration( # pylint: disable=too-many-arguments,unused-argument
|
134
|
+
async def set_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments,unused-argument
|
135
135
|
self,
|
136
136
|
sid: int,
|
137
137
|
period: int = 0,
|
{tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_ambient_light_v3.py
RENAMED
@@ -124,7 +124,7 @@ class BrickletAmbientLightV3(BrickletWithMCU):
|
|
124
124
|
|
125
125
|
return await self.get_illuminance()
|
126
126
|
|
127
|
-
async def set_callback_configuration( # pylint: disable=too-many-arguments
|
127
|
+
async def set_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
128
128
|
self,
|
129
129
|
sid: int,
|
130
130
|
period: int = 0,
|
@@ -167,7 +167,7 @@ class BrickletAmbientLightV3(BrickletWithMCU):
|
|
167
167
|
print(unpack_payload(payload, "I"))
|
168
168
|
return self.__value_to_si(unpack_payload(payload, "I"))
|
169
169
|
|
170
|
-
async def set_illuminance_callback_configuration( # pylint: disable=too-many-arguments
|
170
|
+
async def set_illuminance_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
171
171
|
self,
|
172
172
|
period: int = 0,
|
173
173
|
value_has_to_change: bool = False,
|
@@ -125,7 +125,7 @@ class BrickletAnalogIn(Device):
|
|
125
125
|
return await self.get_voltage()
|
126
126
|
return await self.get_analog_value()
|
127
127
|
|
128
|
-
async def set_callback_configuration( # pylint: disable=too-many-arguments,unused-argument
|
128
|
+
async def set_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments,unused-argument
|
129
129
|
self,
|
130
130
|
sid: int,
|
131
131
|
period: int = 0,
|
@@ -107,7 +107,7 @@ class BrickletBarometer(Device): # pylint: disable=too-many-public-methods
|
|
107
107
|
return await self.get_air_pressure()
|
108
108
|
return await self.get_altitude()
|
109
109
|
|
110
|
-
async def set_callback_configuration( # pylint: disable=too-many-arguments,unused-argument
|
110
|
+
async def set_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments,unused-argument
|
111
111
|
self,
|
112
112
|
sid: int,
|
113
113
|
period: int = 0,
|
{tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_barometer_v2.py
RENAMED
@@ -149,7 +149,7 @@ class BrickletBarometerV2(BrickletWithMCU): # pylint: disable=too-many-public-m
|
|
149
149
|
return await self.get_altitude()
|
150
150
|
return await self.get_temperature()
|
151
151
|
|
152
|
-
async def set_callback_configuration( # pylint: disable=too-many-arguments
|
152
|
+
async def set_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
153
153
|
self,
|
154
154
|
sid: int,
|
155
155
|
period: int = 0,
|
@@ -199,7 +199,7 @@ class BrickletBarometerV2(BrickletWithMCU): # pylint: disable=too-many-public-m
|
|
199
199
|
)
|
200
200
|
return self.__air_pressure_sensor_to_si(unpack_payload(payload, "i"))
|
201
201
|
|
202
|
-
async def set_air_pressure_callback_configuration( # pylint: disable=too-many-arguments
|
202
|
+
async def set_air_pressure_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
203
203
|
self,
|
204
204
|
period: int = 0,
|
205
205
|
value_has_to_change: bool = False,
|
@@ -283,7 +283,7 @@ class BrickletBarometerV2(BrickletWithMCU): # pylint: disable=too-many-public-m
|
|
283
283
|
)
|
284
284
|
return self.__altitude_sensor_to_si(unpack_payload(payload, "i"))
|
285
285
|
|
286
|
-
async def set_altitude_callback_configuration( # pylint: disable=too-many-arguments
|
286
|
+
async def set_altitude_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
287
287
|
self,
|
288
288
|
period: int = 0,
|
289
289
|
value_has_to_change: bool = False,
|
@@ -367,7 +367,7 @@ class BrickletBarometerV2(BrickletWithMCU): # pylint: disable=too-many-public-m
|
|
367
367
|
)
|
368
368
|
return self.__temperature_sensor_to_si(unpack_payload(payload, "i"))
|
369
369
|
|
370
|
-
async def set_temperature_callback_configuration( # pylint: disable=too-many-arguments
|
370
|
+
async def set_temperature_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
371
371
|
self,
|
372
372
|
period: int = 0,
|
373
373
|
value_has_to_change: bool = False,
|
@@ -97,7 +97,7 @@ class BrickletHumidity(Device):
|
|
97
97
|
return await self.get_humidity()
|
98
98
|
return await self.get_analog_value()
|
99
99
|
|
100
|
-
async def set_callback_configuration( # pylint: disable=too-many-arguments,unused-argument
|
100
|
+
async def set_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments,unused-argument
|
101
101
|
self,
|
102
102
|
sid: int,
|
103
103
|
period: int = 0,
|
{tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_humidity_v2.py
RENAMED
@@ -129,7 +129,7 @@ class BrickletHumidityV2(BrickletWithMCU):
|
|
129
129
|
return await self.get_humidity()
|
130
130
|
return await self.get_temperature()
|
131
131
|
|
132
|
-
async def set_callback_configuration( # pylint: disable=too-many-arguments
|
132
|
+
async def set_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
133
133
|
self,
|
134
134
|
sid: int,
|
135
135
|
period: int = 0,
|
@@ -176,7 +176,7 @@ class BrickletHumidityV2(BrickletWithMCU):
|
|
176
176
|
)
|
177
177
|
return self.__humidity_sensor_to_si(unpack_payload(payload, "H"))
|
178
178
|
|
179
|
-
async def set_humidity_callback_configuration( # pylint: disable=too-many-arguments
|
179
|
+
async def set_humidity_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
180
180
|
self,
|
181
181
|
period: int = 0,
|
182
182
|
value_has_to_change: bool = False,
|
@@ -267,7 +267,7 @@ class BrickletHumidityV2(BrickletWithMCU):
|
|
267
267
|
)
|
268
268
|
return self.__temperature_sensor_to_si(unpack_payload(payload, "h"))
|
269
269
|
|
270
|
-
async def set_temperature_callback_configuration( # pylint: disable=too-many-arguments
|
270
|
+
async def set_temperature_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
271
271
|
self,
|
272
272
|
period: int = 0,
|
273
273
|
value_has_to_change: bool = False,
|
@@ -21,7 +21,9 @@ from .devices import (
|
|
21
21
|
SimpleCallbackConfiguration,
|
22
22
|
)
|
23
23
|
from .devices import ThresholdOption as Threshold
|
24
|
-
from .devices import
|
24
|
+
from .devices import (
|
25
|
+
_FunctionID,
|
26
|
+
)
|
25
27
|
from .ip_connection_helper import pack_payload, unpack_payload
|
26
28
|
|
27
29
|
if TYPE_CHECKING:
|
@@ -149,7 +151,7 @@ class BrickletIndustrialDualAnalogInV2(BrickletWithMCU):
|
|
149
151
|
return await self.get_voltage(sid)
|
150
152
|
return await self.get_all_voltages()
|
151
153
|
|
152
|
-
async def set_callback_configuration( # pylint: disable=too-many-arguments
|
154
|
+
async def set_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
153
155
|
self,
|
154
156
|
sid: int,
|
155
157
|
period: int = 0,
|
@@ -197,7 +199,7 @@ class BrickletIndustrialDualAnalogInV2(BrickletWithMCU):
|
|
197
199
|
)
|
198
200
|
return self.__value_to_si(unpack_payload(payload, "i"))
|
199
201
|
|
200
|
-
async def set_voltage_callback_configuration( # pylint: disable=too-many-arguments
|
202
|
+
async def set_voltage_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
201
203
|
self,
|
202
204
|
channel: int,
|
203
205
|
period: int = 0,
|
@@ -430,7 +432,7 @@ class BrickletIndustrialDualAnalogInV2(BrickletWithMCU):
|
|
430
432
|
|
431
433
|
return LedConfig(unpack_payload(payload, "B"))
|
432
434
|
|
433
|
-
async def set_channel_led_status_config( # pylint: disable=too-many-arguments
|
435
|
+
async def set_channel_led_status_config( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
434
436
|
self,
|
435
437
|
channel: int,
|
436
438
|
minimum: float | Decimal,
|
@@ -210,7 +210,7 @@ class BrickletIO16(Device):
|
|
210
210
|
)
|
211
211
|
return unpack_payload(payload, "B")
|
212
212
|
|
213
|
-
async def set_port_configuration( # pylint: disable=too-many-arguments
|
213
|
+
async def set_port_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
214
214
|
self,
|
215
215
|
port: _Port | str,
|
216
216
|
selection_mask: int,
|
@@ -278,7 +278,7 @@ class BrickletIO16(Device):
|
|
278
278
|
)
|
279
279
|
return GetPortConfiguration(*unpack_payload(payload, "B B"))
|
280
280
|
|
281
|
-
async def set_callback_configuration( # pylint: disable=too-many-arguments,unused-argument
|
281
|
+
async def set_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments,unused-argument
|
282
282
|
self,
|
283
283
|
sid: int,
|
284
284
|
period: int = 0,
|
@@ -288,16 +288,16 @@ class BrickletIO16(Device):
|
|
288
288
|
maximum: float | Decimal | None = None,
|
289
289
|
response_expected: bool = True,
|
290
290
|
) -> None:
|
291
|
-
port = Port.A if sid <
|
291
|
+
port = Port.A if sid < 8 else Port.B
|
292
292
|
interrupt_mask = await self.get_port_interrupt(port)
|
293
|
-
interrupt_mask &= ~(1 << (sid %
|
294
|
-
interrupt_mask |= int(bool(period)) << (sid %
|
293
|
+
interrupt_mask &= ~(1 << (sid % 8)) # Reset the bit a position sid
|
294
|
+
interrupt_mask |= int(bool(period)) << (sid % 8) # if period is non-zero, enable the interrupt
|
295
295
|
await self.set_port_interrupt(port, interrupt_mask)
|
296
296
|
|
297
297
|
async def get_callback_configuration(self, sid: int) -> AdvancedCallbackConfiguration:
|
298
|
-
port = Port.A if sid <
|
298
|
+
port = Port.A if sid < 8 else Port.B
|
299
299
|
interrupt_mask = await self.get_port_interrupt(port)
|
300
|
-
value = interrupt_mask & (1 << (sid %
|
300
|
+
value = interrupt_mask & (1 << (sid % 8))
|
301
301
|
return AdvancedCallbackConfiguration(int(bool(value)), False, None, None, None)
|
302
302
|
|
303
303
|
async def set_debounce_period(self, debounce_period: int = 100, response_expected: bool = True) -> None:
|
@@ -360,7 +360,7 @@ class BrickletIO16(Device):
|
|
360
360
|
)
|
361
361
|
return unpack_payload(payload, "B")
|
362
362
|
|
363
|
-
async def set_port_monoflop( # pylint: disable=too-many-arguments
|
363
|
+
async def set_port_monoflop( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
364
364
|
self, port: _Port | str, selection_mask: int, value_mask: int, time: int, response_expected: bool = True
|
365
365
|
) -> None:
|
366
366
|
"""
|
@@ -446,7 +446,7 @@ class BrickletIO16(Device):
|
|
446
446
|
|
447
447
|
.. versionadded:: 2.0.3$nbsp;(Plugin)
|
448
448
|
"""
|
449
|
-
assert isinstance(pin, int) and (0 <= pin <=
|
449
|
+
assert isinstance(pin, int) and (0 <= pin <= 1)
|
450
450
|
|
451
451
|
_, payload = await self.ipcon.send_request(
|
452
452
|
device=self,
|
@@ -497,7 +497,7 @@ class BrickletIO16(Device):
|
|
497
497
|
|
498
498
|
.. versionadded:: 2.0.3$nbsp;(Plugin)
|
499
499
|
"""
|
500
|
-
assert isinstance(pin, int) and (0 <= pin <=
|
500
|
+
assert isinstance(pin, int) and (0 <= pin <= 1)
|
501
501
|
|
502
502
|
_, payload = await self.ipcon.send_request(
|
503
503
|
device=self,
|
@@ -7,9 +7,11 @@ handles conversion of raw units to SI units.
|
|
7
7
|
# pylint: disable=duplicate-code # Many sensors of different generations have a similar API
|
8
8
|
from __future__ import annotations
|
9
9
|
|
10
|
+
import asyncio
|
11
|
+
from asyncio import CancelledError
|
10
12
|
from decimal import Decimal
|
11
13
|
from enum import Enum, unique
|
12
|
-
from typing import TYPE_CHECKING, AsyncGenerator, NamedTuple
|
14
|
+
from typing import TYPE_CHECKING, AsyncGenerator, NamedTuple, TypeAlias, TypedDict
|
13
15
|
|
14
16
|
from .devices import (
|
15
17
|
AdvancedCallbackConfiguration,
|
@@ -19,11 +21,14 @@ from .devices import (
|
|
19
21
|
SimpleCallbackConfiguration,
|
20
22
|
)
|
21
23
|
from .devices import ThresholdOption as Threshold
|
22
|
-
from .devices import
|
24
|
+
from .devices import (
|
25
|
+
_FunctionID,
|
26
|
+
)
|
27
|
+
from .helper import join
|
23
28
|
from .ip_connection_helper import pack_payload, unpack_payload
|
24
29
|
|
25
30
|
if TYPE_CHECKING:
|
26
|
-
from .ip_connection import IPConnectionAsync
|
31
|
+
from .ip_connection import HeaderPayload, IPConnectionAsync
|
27
32
|
|
28
33
|
|
29
34
|
@unique
|
@@ -35,9 +40,10 @@ class CallbackID(Enum):
|
|
35
40
|
INPUT_VALUE = 17
|
36
41
|
ALL_INPUT_VALUE = 18
|
37
42
|
MONOFLOP_DONE = 19
|
43
|
+
EDGE_COUNT = 20
|
38
44
|
|
39
45
|
|
40
|
-
_CallbackID = CallbackID
|
46
|
+
_CallbackID: TypeAlias = CallbackID # pylint: disable=invalid-name
|
41
47
|
|
42
48
|
|
43
49
|
@unique
|
@@ -91,6 +97,14 @@ class EdgeType(Enum):
|
|
91
97
|
_EdgeType = EdgeType
|
92
98
|
|
93
99
|
|
100
|
+
class _EdgeCountTaskConfig(TypedDict):
|
101
|
+
queue: asyncio.Queue[Event]
|
102
|
+
task: asyncio.Task | None
|
103
|
+
lock: asyncio.Lock
|
104
|
+
period: int
|
105
|
+
value_has_to_change: bool
|
106
|
+
|
107
|
+
|
94
108
|
class GetConfiguration(NamedTuple):
|
95
109
|
direction: Direction
|
96
110
|
value: bool
|
@@ -117,7 +131,7 @@ class GetPWMConfiguration(NamedTuple):
|
|
117
131
|
duty_cycle: Decimal
|
118
132
|
|
119
133
|
|
120
|
-
class BrickletIO4V2(BrickletWithMCU):
|
134
|
+
class BrickletIO4V2(BrickletWithMCU): # pylint: disable=too-many-public-methods
|
121
135
|
"""
|
122
136
|
4-channel digital input/output
|
123
137
|
"""
|
@@ -147,6 +161,17 @@ class BrickletIO4V2(BrickletWithMCU):
|
|
147
161
|
super().__init__(self.DEVICE_DISPLAY_NAME, uid, ipcon)
|
148
162
|
|
149
163
|
self.api_version = (2, 0, 0)
|
164
|
+
# The queues are used by the pulse counter
|
165
|
+
self.__counter_queue: dict[int, _EdgeCountTaskConfig] = {
|
166
|
+
channel: {
|
167
|
+
"queue": asyncio.Queue(maxsize=1),
|
168
|
+
"task": None,
|
169
|
+
"lock": asyncio.Lock(),
|
170
|
+
"period": 0,
|
171
|
+
"value_has_to_change": False,
|
172
|
+
}
|
173
|
+
for channel in range(4)
|
174
|
+
}
|
150
175
|
|
151
176
|
async def set_value(
|
152
177
|
self, value: tuple[bool, bool, bool, bool] | list[bool], response_expected: bool = True
|
@@ -271,7 +296,7 @@ class BrickletIO4V2(BrickletWithMCU):
|
|
271
296
|
direction = Direction(direction)
|
272
297
|
return GetConfiguration(direction, value)
|
273
298
|
|
274
|
-
async def set_callback_configuration( # pylint: disable=too-many-arguments,unused-argument
|
299
|
+
async def set_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments,unused-argument
|
275
300
|
self,
|
276
301
|
sid: int,
|
277
302
|
period: int = 0,
|
@@ -281,23 +306,32 @@ class BrickletIO4V2(BrickletWithMCU):
|
|
281
306
|
maximum: float | Decimal | None = None,
|
282
307
|
response_expected: bool = True,
|
283
308
|
) -> None:
|
284
|
-
assert sid in range(
|
309
|
+
assert sid in range(4 + 1 + 4)
|
285
310
|
|
286
311
|
if sid in range(4):
|
287
312
|
await self.set_input_value_callback_configuration(sid, period, value_has_to_change, response_expected)
|
288
|
-
|
313
|
+
elif sid == 4:
|
289
314
|
await self.set_all_input_value_callback_configuration(period, value_has_to_change, response_expected)
|
315
|
+
elif sid in range(5, 5 + 4):
|
316
|
+
await self.set_edge_count_callback_configuration(sid - 5, period, value_has_to_change, response_expected)
|
290
317
|
|
291
318
|
async def get_callback_configuration(self, sid: int) -> AdvancedCallbackConfiguration:
|
292
|
-
assert sid in range(
|
319
|
+
assert sid in range(4 + 1 + 4)
|
293
320
|
|
294
321
|
if sid in range(4):
|
295
322
|
return AdvancedCallbackConfiguration(
|
296
323
|
*(await self.get_input_value_callback_configuration(sid)), option=None, minimum=None, maximum=None
|
297
324
|
)
|
298
|
-
|
299
|
-
|
300
|
-
|
325
|
+
if sid == 4:
|
326
|
+
return AdvancedCallbackConfiguration(
|
327
|
+
*(await self.get_all_input_value_callback_configuration()), option=None, minimum=None, maximum=None
|
328
|
+
)
|
329
|
+
if sid in range(5, 5 + 4):
|
330
|
+
return AdvancedCallbackConfiguration(
|
331
|
+
*(await self.get_edge_count_callback_configuration(sid - 5)), option=None, minimum=None, maximum=None
|
332
|
+
)
|
333
|
+
|
334
|
+
raise ValueError(f"Invalid sid: {sid}")
|
301
335
|
|
302
336
|
async def set_input_value_callback_configuration(
|
303
337
|
self, channel: int, period: int = 0, value_has_to_change: bool = False, response_expected: bool = True
|
@@ -383,6 +417,53 @@ class BrickletIO4V2(BrickletWithMCU):
|
|
383
417
|
)
|
384
418
|
return SimpleCallbackConfiguration(*unpack_payload(payload, "I !"))
|
385
419
|
|
420
|
+
async def set_edge_count_callback_configuration( # pylint: disable=unused-argument
|
421
|
+
self, channel: int, period: int = 0, value_has_to_change: bool = False, response_expected: bool = True
|
422
|
+
) -> None:
|
423
|
+
"""
|
424
|
+
Enable an edge counter task. This task will feed a queue to be read by calling __read_edge_counter().
|
425
|
+
Do note, that the edge counter needs to sync first, so the first value will be available after period * 2.
|
426
|
+
|
427
|
+
Parameters
|
428
|
+
----------
|
429
|
+
channel: int
|
430
|
+
The input channel used for edge counting. Must in range(0,3).
|
431
|
+
period: int
|
432
|
+
Time in ms
|
433
|
+
value_has_to_change: bool
|
434
|
+
If True, the event will be suppressed if there was no change
|
435
|
+
response_expected: bool
|
436
|
+
No effect. Parameter is used for compatibility with other callback configuration functions only.
|
437
|
+
"""
|
438
|
+
assert channel in (0, 1, 2, 3)
|
439
|
+
|
440
|
+
async with self.__counter_queue[channel]["lock"]:
|
441
|
+
task = self.__counter_queue[channel]["task"]
|
442
|
+
# We either need to create a new task or just kill the existing one
|
443
|
+
if task is not None:
|
444
|
+
task.cancel()
|
445
|
+
try:
|
446
|
+
await task
|
447
|
+
except CancelledError:
|
448
|
+
pass
|
449
|
+
|
450
|
+
if period > 0:
|
451
|
+
self.__counter_queue[channel]["task"] = asyncio.create_task(
|
452
|
+
self.__edge_counter_task(channel, period, value_has_to_change)
|
453
|
+
)
|
454
|
+
else:
|
455
|
+
queue = self.__counter_queue[channel]["queue"]
|
456
|
+
if not queue.empty(): # The queue has a maximum of 1 element
|
457
|
+
queue.get_nowait()
|
458
|
+
queue.task_done()
|
459
|
+
self.__counter_queue[channel]["period"] = period
|
460
|
+
self.__counter_queue[channel]["value_has_to_change"] = value_has_to_change
|
461
|
+
|
462
|
+
async def get_edge_count_callback_configuration(self, channel: int) -> SimpleCallbackConfiguration:
|
463
|
+
period = self.__counter_queue[channel]["period"]
|
464
|
+
value_has_to_change = self.__counter_queue[channel]["value_has_to_change"]
|
465
|
+
return SimpleCallbackConfiguration(period=period, value_has_to_change=value_has_to_change)
|
466
|
+
|
386
467
|
async def set_monoflop(self, channel: int, value: bool, time: int, response_expected: bool = True) -> None:
|
387
468
|
"""
|
388
469
|
The first parameter is the desired state of the channel (*true* means output *high*
|
@@ -574,21 +655,59 @@ class BrickletIO4V2(BrickletWithMCU):
|
|
574
655
|
frequency, duty_cycle = unpack_payload(payload, "I H")
|
575
656
|
return GetPWMConfiguration(Decimal(frequency) / 10, Decimal(duty_cycle) / 10000)
|
576
657
|
|
577
|
-
async def
|
658
|
+
async def __edge_counter_task(self, channel: int, period: int, value_has_to_change: bool) -> None:
|
659
|
+
previous_value: int | None = None
|
660
|
+
# Throw away the first value, because we need to reset and sync the internal counter of the IO bricklet.
|
661
|
+
try:
|
662
|
+
await asyncio.gather(self.get_edge_count(channel, reset_counter=True), asyncio.sleep(period / 1000))
|
663
|
+
while "not canceled":
|
664
|
+
value, _ = await asyncio.gather(
|
665
|
+
self.get_edge_count(channel, reset_counter=True), asyncio.sleep(period / 1000)
|
666
|
+
)
|
667
|
+
queue = self.__counter_queue[channel]["queue"]
|
668
|
+
if not value_has_to_change or previous_value != value:
|
669
|
+
previous_value = value
|
670
|
+
event = Event(self, sid=channel + 5, function_id=CallbackID.EDGE_COUNT, payload=value)
|
671
|
+
try:
|
672
|
+
queue.put_nowait(event)
|
673
|
+
except asyncio.QueueFull:
|
674
|
+
queue.get_nowait()
|
675
|
+
queue.put_nowait(event)
|
676
|
+
except ValueError:
|
677
|
+
# raised if the channel is set to output. We will then stop the edge counter callback without notice.
|
678
|
+
pass
|
679
|
+
|
680
|
+
async def __read_edge_counter(self, channel: int) -> AsyncGenerator[Event, None]:
|
681
|
+
while "not cancelled":
|
682
|
+
queue = self.__counter_queue[channel]["queue"]
|
683
|
+
yield await queue.get()
|
684
|
+
queue.task_done()
|
685
|
+
|
686
|
+
async def __read_callback_events(
|
578
687
|
self,
|
579
|
-
events:
|
580
|
-
sids: tuple[int, ...] | list[int]
|
688
|
+
events: set[_CallbackID],
|
689
|
+
sids: tuple[int, ...] | list[int],
|
581
690
|
) -> AsyncGenerator[Event, None]:
|
582
|
-
|
691
|
+
"""
|
692
|
+
This functions connects to the ip connection and retrieves callback events for a given list of events or sids.
|
693
|
+
The callback must be enabled prior to registering to this generator.
|
583
694
|
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
695
|
+
Parameters
|
696
|
+
----------
|
697
|
+
events: set of CallbackID
|
698
|
+
Any value of CallbackID.INPUT_VALUE, CallbackID.ALL_INPUT_VALUE or CallbackID.MONOFLOP_DONE. Other values
|
699
|
+
in the set will be ignored.
|
700
|
+
sids: tuple or list of int
|
701
|
+
A tuple with ints in range of range(4). Other sids will be ignored.
|
702
|
+
|
703
|
+
Yields
|
704
|
+
-------
|
705
|
+
Event
|
706
|
+
Events matching the desired sid/event filters
|
589
707
|
|
708
|
+
"""
|
590
709
|
if not events and not sids:
|
591
|
-
|
710
|
+
return
|
592
711
|
|
593
712
|
async for header, payload in super()._read_events():
|
594
713
|
try:
|
@@ -599,19 +718,52 @@ class BrickletIO4V2(BrickletWithMCU):
|
|
599
718
|
|
600
719
|
if function_id is CallbackID.INPUT_VALUE:
|
601
720
|
sid, value_has_changed, value = unpack_payload(payload, self.CALLBACK_FORMATS[function_id])
|
602
|
-
if function_id in
|
721
|
+
if function_id in events or sid in sids:
|
603
722
|
yield Event(self, sid, function_id, value, value_has_changed)
|
604
723
|
continue
|
605
724
|
elif function_id is CallbackID.MONOFLOP_DONE:
|
606
725
|
sid, value = unpack_payload(payload, self.CALLBACK_FORMATS[function_id])
|
607
|
-
if function_id in
|
726
|
+
if function_id in events or sid in sids:
|
608
727
|
yield Event(self, sid, function_id, value)
|
609
728
|
continue
|
610
729
|
else:
|
611
730
|
changed_sids, values = unpack_payload(payload, self.CALLBACK_FORMATS[function_id])
|
612
|
-
if function_id in
|
731
|
+
if function_id in events:
|
613
732
|
# Use a special sid for the CallbackID.ALL_INPUT_VALUE, because it returns a tuple
|
614
733
|
yield Event(self, 4, function_id, values, changed_sids)
|
615
734
|
else:
|
616
735
|
for sid in sids:
|
617
736
|
yield Event(self, sid, function_id, values[sid], changed_sids[sid])
|
737
|
+
|
738
|
+
async def read_events(
|
739
|
+
self,
|
740
|
+
events: tuple[int | _CallbackID, ...] | list[int | _CallbackID] | None = None,
|
741
|
+
sids: tuple[int, ...] | list[int] | None = None,
|
742
|
+
) -> AsyncGenerator[Event, None]:
|
743
|
+
assert events is None or sids is None
|
744
|
+
|
745
|
+
sids = tuple() if sids is None else sids
|
746
|
+
|
747
|
+
registered_edge_count_sids = tuple(sid for sid in sids if sid in range(5, 5 + 4))
|
748
|
+
registered_callback_events: set[_CallbackID] = set()
|
749
|
+
|
750
|
+
if events:
|
751
|
+
for event in events:
|
752
|
+
event = self.CallbackID(event)
|
753
|
+
# CallbackID.PULSE_COUNT is not a regular callback, so it must be treated special
|
754
|
+
if event != CallbackID.EDGE_COUNT:
|
755
|
+
registered_callback_events.add(event)
|
756
|
+
else:
|
757
|
+
registered_edge_count_sids = tuple(range(5, 5 + 4))
|
758
|
+
registered_callback_sids = tuple(sid for sid in sids if sid in range(5))
|
759
|
+
|
760
|
+
# register all callback events if no specific filter is given
|
761
|
+
if not events and not sids:
|
762
|
+
registered_callback_events = set(self.CALLBACK_FORMATS.keys())
|
763
|
+
registered_edge_count_sids = tuple(range(5, 5 + 4))
|
764
|
+
|
765
|
+
async for res in join(
|
766
|
+
self.__read_callback_events(registered_callback_events, registered_callback_sids),
|
767
|
+
*(self.__read_edge_counter(sid - 5) for sid in registered_edge_count_sids),
|
768
|
+
):
|
769
|
+
yield res
|
@@ -86,7 +86,7 @@ class BrickletMoisture(Device):
|
|
86
86
|
|
87
87
|
return await self.get_moisture_value()
|
88
88
|
|
89
|
-
async def set_callback_configuration( # pylint: disable=too-many-arguments,unused-argument
|
89
|
+
async def set_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments,unused-argument
|
90
90
|
self,
|
91
91
|
sid: int,
|
92
92
|
period: int = 0,
|
@@ -181,7 +181,7 @@ class BrickletPtc(Device): # pylint: disable=too-many-public-methods
|
|
181
181
|
return await self.get_resistance()
|
182
182
|
return await self.is_sensor_connected()
|
183
183
|
|
184
|
-
async def set_callback_configuration( # pylint: disable=too-many-arguments,unused-argument
|
184
|
+
async def set_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments,unused-argument
|
185
185
|
self,
|
186
186
|
sid: int,
|
187
187
|
period: int = 0,
|
@@ -178,7 +178,7 @@ class BrickletPtcV2(BrickletWithMCU):
|
|
178
178
|
return await self.get_resistance()
|
179
179
|
return await self.is_sensor_connected()
|
180
180
|
|
181
|
-
async def set_callback_configuration( # pylint: disable=too-many-arguments
|
181
|
+
async def set_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
182
182
|
self,
|
183
183
|
sid: int,
|
184
184
|
period: int = 0,
|
@@ -227,7 +227,7 @@ class BrickletPtcV2(BrickletWithMCU):
|
|
227
227
|
)
|
228
228
|
return self.__value_to_si_temperature(unpack_payload(payload, "i"))
|
229
229
|
|
230
|
-
async def set_temperature_callback_configuration( # pylint: disable=too-many-arguments
|
230
|
+
async def set_temperature_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
231
231
|
self,
|
232
232
|
period: int = 0,
|
233
233
|
value_has_to_change: bool = False,
|
@@ -313,7 +313,7 @@ class BrickletPtcV2(BrickletWithMCU):
|
|
313
313
|
)
|
314
314
|
return self.__value_to_si_resistance(unpack_payload(payload, "i"))
|
315
315
|
|
316
|
-
async def set_resistance_callback_configuration( # pylint: disable=too-many-arguments
|
316
|
+
async def set_resistance_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
317
317
|
self,
|
318
318
|
period: int = 0,
|
319
319
|
value_has_to_change: bool = False,
|
@@ -262,7 +262,7 @@ class BrickletRS232V2(BrickletWithMCU):
|
|
262
262
|
|
263
263
|
return unpack_payload(payload, "!")
|
264
264
|
|
265
|
-
async def set_configuration( # pylint: disable=too-many-arguments
|
265
|
+
async def set_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
266
266
|
self,
|
267
267
|
baudrate: int = 115200,
|
268
268
|
parity: _Parity | int = Parity.NONE,
|
@@ -123,7 +123,7 @@ class BrickletSegmentDisplay4x7(Device):
|
|
123
123
|
)
|
124
124
|
return GetSegments(*unpack_payload(payload, "4B B !"))
|
125
125
|
|
126
|
-
async def start_counter( # pylint: disable=too-many-arguments
|
126
|
+
async def start_counter( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
127
127
|
self, value_from: int, value_to: int, increment: int = 1, length: int = 1000, response_expected: bool = True
|
128
128
|
) -> None:
|
129
129
|
"""
|
@@ -204,7 +204,7 @@ class BrickletSegmentDisplay4x7V2(BrickletWithMCU):
|
|
204
204
|
|
205
205
|
return unpack_payload(payload, "!")
|
206
206
|
|
207
|
-
async def start_counter( # pylint: disable=too-many-arguments
|
207
|
+
async def start_counter( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
208
208
|
self, value_from: int, value_to: int, increment: int, length: int, response_expected: bool = True
|
209
209
|
) -> None:
|
210
210
|
"""
|
{tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_temperature.py
RENAMED
@@ -102,7 +102,7 @@ class BrickletTemperature(Device):
|
|
102
102
|
|
103
103
|
return await self.get_temperature()
|
104
104
|
|
105
|
-
async def set_callback_configuration( # pylint: disable=too-many-arguments,unused-argument
|
105
|
+
async def set_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments,unused-argument
|
106
106
|
self,
|
107
107
|
sid: int,
|
108
108
|
period: int = 0,
|
{tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_temperature_v2.py
RENAMED
@@ -94,7 +94,7 @@ class BrickletTemperatureV2(BrickletWithMCU):
|
|
94
94
|
|
95
95
|
return await self.get_temperature()
|
96
96
|
|
97
|
-
async def set_callback_configuration( # pylint: disable=too-many-arguments
|
97
|
+
async def set_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
98
98
|
self,
|
99
99
|
sid: int,
|
100
100
|
period: int = 0,
|
@@ -133,7 +133,7 @@ class BrickletTemperatureV2(BrickletWithMCU):
|
|
133
133
|
)
|
134
134
|
return self.__value_to_si(unpack_payload(payload, "h"))
|
135
135
|
|
136
|
-
async def set_temperature_callback_configuration( # pylint: disable=too-many-arguments
|
136
|
+
async def set_temperature_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
137
137
|
self,
|
138
138
|
period: int = 0,
|
139
139
|
value_has_to_change: bool = False,
|
{tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_thermocouple_v2.py
RENAMED
@@ -182,7 +182,7 @@ class BrickletThermocoupleV2(BrickletWithMCU):
|
|
182
182
|
return await self.get_error_state()
|
183
183
|
raise ValueError(f"Invalid sid: {sid}. sid must be in (0, 1).")
|
184
184
|
|
185
|
-
async def set_callback_configuration( # pylint: disable=too-many-arguments
|
185
|
+
async def set_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
186
186
|
self,
|
187
187
|
sid: int,
|
188
188
|
period: int = 0,
|
@@ -226,7 +226,7 @@ class BrickletThermocoupleV2(BrickletWithMCU):
|
|
226
226
|
)
|
227
227
|
return self.__value_to_si(unpack_payload(payload, "i"))
|
228
228
|
|
229
|
-
async def set_temperature_callback_configuration( # pylint: disable=too-many-arguments
|
229
|
+
async def set_temperature_callback_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
230
230
|
self,
|
231
231
|
period: int = 0,
|
232
232
|
value_has_to_change: bool = False,
|
@@ -0,0 +1,42 @@
|
|
1
|
+
"""
|
2
|
+
General helper functions used by multiple modules.
|
3
|
+
"""
|
4
|
+
|
5
|
+
import asyncio
|
6
|
+
from typing import AsyncGenerator, TypeVar
|
7
|
+
|
8
|
+
T = TypeVar("T")
|
9
|
+
|
10
|
+
|
11
|
+
async def _read_into_queue(
|
12
|
+
gen: AsyncGenerator[T, None],
|
13
|
+
queue: asyncio.Queue[T],
|
14
|
+
done: asyncio.Semaphore,
|
15
|
+
) -> None:
|
16
|
+
try:
|
17
|
+
async for item in gen:
|
18
|
+
await queue.put(item)
|
19
|
+
finally:
|
20
|
+
# Once done, notify the semaphore
|
21
|
+
await done.acquire()
|
22
|
+
|
23
|
+
|
24
|
+
async def join(*generators: AsyncGenerator[T, None]) -> AsyncGenerator[T, None]:
|
25
|
+
queue: asyncio.Queue[T] = asyncio.Queue(maxsize=1)
|
26
|
+
done_semaphore = asyncio.Semaphore(len(generators))
|
27
|
+
|
28
|
+
# Read from each given generator into the shared queue.
|
29
|
+
producers = [asyncio.create_task(_read_into_queue(gen, queue, done_semaphore)) for gen in generators]
|
30
|
+
|
31
|
+
# Read items off the queue until it is empty and the semaphore value is down to zero.
|
32
|
+
while not done_semaphore.locked() or not queue.empty():
|
33
|
+
try:
|
34
|
+
yield await asyncio.wait_for(queue.get(), 0.001)
|
35
|
+
except TimeoutError:
|
36
|
+
continue
|
37
|
+
|
38
|
+
# Not strictly needed, but usually a good idea to await tasks, they are already finished here.
|
39
|
+
try:
|
40
|
+
await asyncio.wait_for(asyncio.gather(*producers), 0)
|
41
|
+
except TimeoutError as exc:
|
42
|
+
raise NotImplementedError("Impossible state: expected all tasks to be exhausted") from exc
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: tinkerforge-async
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.6.0
|
4
4
|
Summary: Python3 AsyncIO Tinkerforge driver
|
5
5
|
Author-email: Patrick Baus <patrick.baus@physik.tu-darmstadt.de>
|
6
6
|
License: GNU General Public License v3 (GPLv3)
|
@@ -9,8 +9,6 @@ Project-URL: Bug Tracker, https://github.com/PatrickBaus/tinkerforge_async/issue
|
|
9
9
|
Project-URL: Download, https://github.com/PatrickBaus/tinkerforge_async/releases
|
10
10
|
Keywords: IoT,Tinkerforge,API
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
12
|
-
Classifier: Programming Language :: Python :: 3.7
|
13
|
-
Classifier: Programming Language :: Python :: 3.8
|
14
12
|
Classifier: Programming Language :: Python :: 3.9
|
15
13
|
Classifier: Programming Language :: Python :: 3.10
|
16
14
|
Classifier: Programming Language :: Python :: 3.11
|
@@ -44,6 +42,7 @@ Requires-Dist: mypy; extra == "test"
|
|
44
42
|
Requires-Dist: pylint; extra == "test"
|
45
43
|
Requires-Dist: pytest; extra == "test"
|
46
44
|
Requires-Dist: setuptools; extra == "test"
|
45
|
+
Dynamic: license-file
|
47
46
|
|
48
47
|
[](../../actions/workflows/pylint.yml)
|
49
48
|
[](https://pypi.org/project/tinkerforge-async/)
|
@@ -106,7 +105,7 @@ pip install tinkerforge-async
|
|
106
105
|
# Changes made to the API
|
107
106
|
Some design choices of the original Tinkerforge API are overly complex. I therefore replaced them with a simpler and more intuitive approach. A list of things that were changed can be found below:
|
108
107
|
## Design Changes
|
109
|
-
- Only Python 3 is supported (3.
|
108
|
+
- Only Python 3 is supported (3.9+)
|
110
109
|
- Replaced threads with an async event loop
|
111
110
|
- Completely rewritten how responses from bricks/bricklets work. All setters now have a `response_expected` parameter, which is set to `True` by default. If there is an error when calling the function, it will then raise an exception - either an `AttributeError` if the function is unknown, or a `ValueError` if one or more parameters are invalid.
|
112
111
|
|
@@ -188,9 +187,11 @@ Some design choices of the original Tinkerforge API are overly complex. I theref
|
|
188
187
|
- `IPConnection.register_callback(callback_id, function)`: Replaced by `register_event_queue()`
|
189
188
|
- `IPConnection.connect(host, port=4223, authentication_secret='')`: If `authentication_secret` is not empty, try to authenticate.
|
190
189
|
|
191
|
-
- ### [
|
190
|
+
- ### [IO-4 Bricklet 2.0](https://www.tinkerforge.com/de/doc/Software/Bricklets/IO4V2_Bricklet_Python.html)
|
192
191
|
- `BrickletIO4V2.set_pwm_configuration()` will now take the frequency in units of Hz and the duty cycle is normalized to 1, so it will take a float from [0...1].
|
193
|
-
- `BrickletIO4V2.get_pwm_configuration()` will return the frequency in units of
|
192
|
+
- `BrickletIO4V2.get_pwm_configuration()` will return the frequency in units of Hz and the duty cycle is normalized to 1.
|
193
|
+
- `BrickletIO4V2.set_edge_count_callback_configuration()` sets the callback configuration for the edge counter callback. Its secondary ids are in [5...8] for channels [0...3].
|
194
|
+
- `BrickletIO4V2.get_edge_count_callback_configuration()` returns the callback configuration for the edge counter callback.
|
194
195
|
|
195
196
|
- ### [Master Brick](https://www.tinkerforge.com/en/doc/Software/Bricks/Master_Brick_Python.html)
|
196
197
|
- `BrickMaster.set_wifi_configuration()`/`BrickMaster.get_wifi_configuration()` will take/return all ips in natural order
|
@@ -210,7 +211,6 @@ Some design choices of the original Tinkerforge API are overly complex. I theref
|
|
210
211
|
- `BrickletThermocoupleV2()` takes an additional parameter to define the type of sensor. The options are of type `BrickletThermocoupleV2.SensorType`. The default is `BrickletPtc.SensorType.TYPE_K`.
|
211
212
|
- `BrickletThermocoupleV2.sensor_type` getter and setter to change the type of sensor used.
|
212
213
|
|
213
|
-
|
214
214
|
- ### [Segment Display 4x7 Bricklet 2.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Segment_Display_4x7_V2.html)
|
215
215
|
- `BrickletSegmentDisplay4x7V2.set_segments()` takes a `list`/`tuple` of 4 `int` instead of digit0, digit1, digit2, digit3. This is the same API as the older [Segment Display 4x7 Bricklet](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Segment_Display_4x7.html).
|
216
216
|
|
@@ -30,6 +30,7 @@ tinkerforge_async/bricklet_temperature_v2.py
|
|
30
30
|
tinkerforge_async/bricklet_thermocouple_v2.py
|
31
31
|
tinkerforge_async/device_factory.py
|
32
32
|
tinkerforge_async/devices.py
|
33
|
+
tinkerforge_async/helper.py
|
33
34
|
tinkerforge_async/ip_connection.py
|
34
35
|
tinkerforge_async/ip_connection_helper.py
|
35
36
|
tinkerforge_async.egg-info/PKG-INFO
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_industrial_ptc.py
RENAMED
File without changes
|
File without changes
|
{tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/bricklet_motion_detector_v2.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async/ip_connection_helper.py
RENAMED
File without changes
|
{tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async.egg-info/dependency_links.txt
RENAMED
File without changes
|
File without changes
|
{tinkerforge_async-1.5.3 → tinkerforge_async-1.6.0}/tinkerforge_async.egg-info/top_level.txt
RENAMED
File without changes
|