tinkerforge-async 1.5.2__py3-none-any.whl → 1.6.0__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.
Files changed (37) hide show
  1. tinkerforge_async/__init__.py +1 -0
  2. tinkerforge_async/_version.py +1 -1
  3. tinkerforge_async/async_event_bus.py +3 -2
  4. tinkerforge_async/brick_master.py +8 -7
  5. tinkerforge_async/bricklet_ambient_light_v2.py +2 -1
  6. tinkerforge_async/bricklet_ambient_light_v3.py +3 -2
  7. tinkerforge_async/bricklet_analog_in.py +2 -1
  8. tinkerforge_async/bricklet_barometer.py +2 -1
  9. tinkerforge_async/bricklet_barometer_v2.py +5 -4
  10. tinkerforge_async/bricklet_humidity.py +2 -1
  11. tinkerforge_async/bricklet_humidity_v2.py +4 -3
  12. tinkerforge_async/bricklet_industrial_dual_analog_in_v2.py +7 -4
  13. tinkerforge_async/bricklet_industrial_ptc.py +1 -0
  14. tinkerforge_async/bricklet_io16.py +11 -10
  15. tinkerforge_async/bricklet_io4_v2.py +178 -25
  16. tinkerforge_async/bricklet_isolator.py +1 -0
  17. tinkerforge_async/bricklet_moisture.py +2 -1
  18. tinkerforge_async/bricklet_motion_detector_v2.py +1 -0
  19. tinkerforge_async/bricklet_ptc.py +2 -1
  20. tinkerforge_async/bricklet_ptc_v2.py +4 -3
  21. tinkerforge_async/bricklet_rs232_v2.py +2 -1
  22. tinkerforge_async/bricklet_segment_display_4x7.py +2 -1
  23. tinkerforge_async/bricklet_segment_display_4x7_v2.py +2 -1
  24. tinkerforge_async/bricklet_temperature.py +2 -1
  25. tinkerforge_async/bricklet_temperature_v2.py +3 -2
  26. tinkerforge_async/bricklet_thermocouple_v2.py +3 -2
  27. tinkerforge_async/device_factory.py +1 -0
  28. tinkerforge_async/devices.py +1 -0
  29. tinkerforge_async/helper.py +42 -0
  30. tinkerforge_async/ip_connection.py +9 -9
  31. tinkerforge_async/ip_connection_helper.py +1 -0
  32. {tinkerforge_async-1.5.2.dist-info → tinkerforge_async-1.6.0.dist-info}/METADATA +24 -24
  33. tinkerforge_async-1.6.0.dist-info/RECORD +36 -0
  34. {tinkerforge_async-1.5.2.dist-info → tinkerforge_async-1.6.0.dist-info}/WHEEL +1 -1
  35. tinkerforge_async-1.5.2.dist-info/RECORD +0 -35
  36. {tinkerforge_async-1.5.2.dist-info → tinkerforge_async-1.6.0.dist-info/licenses}/LICENSE +0 -0
  37. {tinkerforge_async-1.5.2.dist-info → tinkerforge_async-1.6.0.dist-info}/top_level.txt +0 -0
@@ -3,6 +3,7 @@ This is a reimplementation of the Tinkerforge Python bindings
3
3
  ([original Python bindings](https://www.tinkerforge.com/en/doc/Software/API_Bindings_Python.html)) using Python 3
4
4
  asyncio.
5
5
  """
6
+
6
7
  from ._version import __version__
7
8
  from .device_factory import device_factory
8
9
  from .ip_connection import IPConnectionAsync
@@ -1,2 +1,2 @@
1
1
  # pylint: disable=missing-module-docstring
2
- __version__ = "1.5.2"
2
+ __version__ = "1.6.0"
@@ -2,13 +2,14 @@
2
2
  A lightweight event bus for the asyncio framework, that relies on asynchronous
3
3
  generators to deliver messages.
4
4
  """
5
+
5
6
  import asyncio
6
7
  from typing import Any, AsyncGenerator
7
8
 
8
9
 
9
10
  class EventBus:
10
11
  """
11
- An event bus, that is using the async generator syntax for distributing events.
12
+ An event bus that is using the async generator syntax for distributing events.
12
13
  It uses dicts and sets internally to ensure good performance.
13
14
  """
14
15
 
@@ -17,7 +18,7 @@ class EventBus:
17
18
 
18
19
  async def register(self, event_name: str) -> AsyncGenerator[Any, None]:
19
20
  """
20
- The async generator, that yields events subscribed to `event_name`.
21
+ The async generator that yields events subscribed to `event_name`.
21
22
 
22
23
  Parameters
23
24
  ----------
@@ -3,6 +3,7 @@ Module for the Tinkerforge Master Brick (https://www.tinkerforge.com/en/doc/Hard
3
3
  implemented using Python AsyncIO. It does the low-level communication with the Tinkerforge ip connection and also
4
4
  handles conversion of raw units to SI units.
5
5
  """
6
+
6
7
  # pylint: disable=too-many-lines
7
8
  from __future__ import annotations
8
9
 
@@ -1251,7 +1252,7 @@ class BrickMaster(DeviceWithMCU): # pylint: disable=too-many-public-methods
1251
1252
  )
1252
1253
  return unpack_payload(payload, "!")
1253
1254
 
1254
- 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
1255
1256
  self,
1256
1257
  ssid: str | bytes,
1257
1258
  connection: _WifiConnection | int,
@@ -1333,7 +1334,7 @@ class BrickMaster(DeviceWithMCU): # pylint: disable=too-many-public-methods
1333
1334
  ssid, WifiConnection(connection), ip_addr[::-1], subnet_mask[::-1], gateway[::-1], port
1334
1335
  )
1335
1336
 
1336
- 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
1337
1338
  self,
1338
1339
  encryption: WifiEncryptionMode,
1339
1340
  key_index: int = 1,
@@ -2083,7 +2084,7 @@ class BrickMaster(DeviceWithMCU): # pylint: disable=too-many-public-methods
2083
2084
 
2084
2085
  return unpack_payload(payload, "!")
2085
2086
 
2086
- 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
2087
2088
  self,
2088
2089
  connection: _EthernetConnection,
2089
2090
  ip_address: tuple[int, int, int, int] = (0, 0, 0, 0),
@@ -2509,7 +2510,7 @@ class BrickMaster(DeviceWithMCU): # pylint: disable=too-many-public-methods
2509
2510
 
2510
2511
  return unpack_payload(payload, "64s")
2511
2512
 
2512
- 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
2513
2514
  self,
2514
2515
  port: int = 4223,
2515
2516
  websocket_port: int = 4280,
@@ -2635,7 +2636,7 @@ class BrickMaster(DeviceWithMCU): # pylint: disable=too-many-public-methods
2635
2636
  ap_connected_count,
2636
2637
  )
2637
2638
 
2638
- 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
2639
2640
  self,
2640
2641
  enable: bool = True,
2641
2642
  ssid: bytes | str = "tinkerforge",
@@ -2808,7 +2809,7 @@ class BrickMaster(DeviceWithMCU): # pylint: disable=too-many-public-methods
2808
2809
  )
2809
2810
  return unpack_payload(payload, "64s")
2810
2811
 
2811
- 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
2812
2813
  self,
2813
2814
  enable: bool = True,
2814
2815
  ssid: bytes | str = "WIFI Extension 2.0 Access Point",
@@ -3025,7 +3026,7 @@ class BrickMaster(DeviceWithMCU): # pylint: disable=too-many-public-methods
3025
3026
  )
3026
3027
  return unpack_payload(payload, "!")
3027
3028
 
3028
- 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
3029
3030
  self,
3030
3031
  enable: bool = False,
3031
3032
  root_ip: tuple[int, int, int, int] = (0, 0, 0, 0),
@@ -3,6 +3,7 @@ Module for the Tinkerforge Ambient Light Bricklet 2.0
3
3
  (https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Ambient_Light_V2.html) implemented using Python asyncio. It does
4
4
  the low-level communication with the Tinkerforge ip connection and also handles conversion of raw units to SI units.
5
5
  """
6
+
6
7
  # pylint: disable=duplicate-code # Many sensors of different generations have a similar API
7
8
  from __future__ import annotations
8
9
 
@@ -130,7 +131,7 @@ class BrickletAmbientLightV2(Device):
130
131
 
131
132
  return await self.get_illuminance()
132
133
 
133
- 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
134
135
  self,
135
136
  sid: int,
136
137
  period: int = 0,
@@ -3,6 +3,7 @@ Module for the Tinkerforge Ambient Light Bricklet 3.0
3
3
  (https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Ambient_Light_V3.html) implemented using Python asyncio. It does
4
4
  the low-level communication with the Tinkerforge ip connection and also handles conversion of raw units to SI units.
5
5
  """
6
+
6
7
  # pylint: disable=duplicate-code # Many sensors of different generations have a similar API
7
8
  from __future__ import annotations
8
9
 
@@ -123,7 +124,7 @@ class BrickletAmbientLightV3(BrickletWithMCU):
123
124
 
124
125
  return await self.get_illuminance()
125
126
 
126
- 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
127
128
  self,
128
129
  sid: int,
129
130
  period: int = 0,
@@ -166,7 +167,7 @@ class BrickletAmbientLightV3(BrickletWithMCU):
166
167
  print(unpack_payload(payload, "I"))
167
168
  return self.__value_to_si(unpack_payload(payload, "I"))
168
169
 
169
- 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
170
171
  self,
171
172
  period: int = 0,
172
173
  value_has_to_change: bool = False,
@@ -3,6 +3,7 @@ Module for the Tinkerforge Analog In Bricklet (https://www.tinkerforge.com/en/do
3
3
  implemented using Python asyncio. It does the low-level communication with the Tinkerforge ip connection and also
4
4
  handles conversion of raw units to SI units.
5
5
  """
6
+
6
7
  # pylint: disable=duplicate-code # Many sensors of different generations have a similar API
7
8
  from __future__ import annotations
8
9
 
@@ -124,7 +125,7 @@ class BrickletAnalogIn(Device):
124
125
  return await self.get_voltage()
125
126
  return await self.get_analog_value()
126
127
 
127
- 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
128
129
  self,
129
130
  sid: int,
130
131
  period: int = 0,
@@ -3,6 +3,7 @@ Module for the Tinkerforge Barometer Bricklet (https://www.tinkerforge.com/en/do
3
3
  implemented using Python AsyncIO. It does the low-level communication with the Tinkerforge ip connection and also
4
4
  handles conversion of raw units to SI units.
5
5
  """
6
+
6
7
  # pylint: disable=duplicate-code # Many sensors of different generations have a similar API
7
8
  from __future__ import annotations
8
9
 
@@ -106,7 +107,7 @@ class BrickletBarometer(Device): # pylint: disable=too-many-public-methods
106
107
  return await self.get_air_pressure()
107
108
  return await self.get_altitude()
108
109
 
109
- 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
110
111
  self,
111
112
  sid: int,
112
113
  period: int = 0,
@@ -3,6 +3,7 @@ Module for the Tinkerforge Barometer Bricklet 2.0
3
3
  (https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Barometer_V2.html) implemented using Python asyncio. It does the
4
4
  low-level communication with the Tinkerforge ip connection and also handles conversion of raw units to SI units.
5
5
  """
6
+
6
7
  # pylint: disable=duplicate-code # Many sensors of different generations have a similar API
7
8
  from __future__ import annotations
8
9
 
@@ -148,7 +149,7 @@ class BrickletBarometerV2(BrickletWithMCU): # pylint: disable=too-many-public-m
148
149
  return await self.get_altitude()
149
150
  return await self.get_temperature()
150
151
 
151
- 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
152
153
  self,
153
154
  sid: int,
154
155
  period: int = 0,
@@ -198,7 +199,7 @@ class BrickletBarometerV2(BrickletWithMCU): # pylint: disable=too-many-public-m
198
199
  )
199
200
  return self.__air_pressure_sensor_to_si(unpack_payload(payload, "i"))
200
201
 
201
- 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
202
203
  self,
203
204
  period: int = 0,
204
205
  value_has_to_change: bool = False,
@@ -282,7 +283,7 @@ class BrickletBarometerV2(BrickletWithMCU): # pylint: disable=too-many-public-m
282
283
  )
283
284
  return self.__altitude_sensor_to_si(unpack_payload(payload, "i"))
284
285
 
285
- 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
286
287
  self,
287
288
  period: int = 0,
288
289
  value_has_to_change: bool = False,
@@ -366,7 +367,7 @@ class BrickletBarometerV2(BrickletWithMCU): # pylint: disable=too-many-public-m
366
367
  )
367
368
  return self.__temperature_sensor_to_si(unpack_payload(payload, "i"))
368
369
 
369
- 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
370
371
  self,
371
372
  period: int = 0,
372
373
  value_has_to_change: bool = False,
@@ -3,6 +3,7 @@ Module for the Tinkerforge Humidity Bricklet (https://www.tinkerforge.com/en/doc
3
3
  implemented using Python AsyncIO. It does the low-level communication with the Tinkerforge ip connection and also
4
4
  handles conversion of raw units to SI units.
5
5
  """
6
+
6
7
  # pylint: disable=duplicate-code # Many sensors of different generations have a similar API
7
8
  from __future__ import annotations
8
9
 
@@ -96,7 +97,7 @@ class BrickletHumidity(Device):
96
97
  return await self.get_humidity()
97
98
  return await self.get_analog_value()
98
99
 
99
- 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
100
101
  self,
101
102
  sid: int,
102
103
  period: int = 0,
@@ -3,6 +3,7 @@ Module for the Tinkerforge Humidity Bricklet 2.0
3
3
  (https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Humidity_V2.html) implemented using Python asyncIO. It does the
4
4
  low-level communication with the Tinkerforge ip connection and also handles conversion of raw units to SI units.
5
5
  """
6
+
6
7
  # pylint: disable=duplicate-code # Many sensors of different generations have a similar API
7
8
  from __future__ import annotations
8
9
 
@@ -128,7 +129,7 @@ class BrickletHumidityV2(BrickletWithMCU):
128
129
  return await self.get_humidity()
129
130
  return await self.get_temperature()
130
131
 
131
- 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
132
133
  self,
133
134
  sid: int,
134
135
  period: int = 0,
@@ -175,7 +176,7 @@ class BrickletHumidityV2(BrickletWithMCU):
175
176
  )
176
177
  return self.__humidity_sensor_to_si(unpack_payload(payload, "H"))
177
178
 
178
- 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
179
180
  self,
180
181
  period: int = 0,
181
182
  value_has_to_change: bool = False,
@@ -266,7 +267,7 @@ class BrickletHumidityV2(BrickletWithMCU):
266
267
  )
267
268
  return self.__temperature_sensor_to_si(unpack_payload(payload, "h"))
268
269
 
269
- 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
270
271
  self,
271
272
  period: int = 0,
272
273
  value_has_to_change: bool = False,
@@ -4,6 +4,7 @@ Module for the Tinkerforge Industrial Dual Analog In Bricklet 2.0
4
4
  asyncio. It does the low-level communication with the Tinkerforge ip connection and also handles conversion of raw units
5
5
  to SI units.
6
6
  """
7
+
7
8
  # pylint: disable=duplicate-code # Many sensors of different generations have a similar API
8
9
  from __future__ import annotations
9
10
 
@@ -20,7 +21,9 @@ from .devices import (
20
21
  SimpleCallbackConfiguration,
21
22
  )
22
23
  from .devices import ThresholdOption as Threshold
23
- from .devices import _FunctionID
24
+ from .devices import (
25
+ _FunctionID,
26
+ )
24
27
  from .ip_connection_helper import pack_payload, unpack_payload
25
28
 
26
29
  if TYPE_CHECKING:
@@ -148,7 +151,7 @@ class BrickletIndustrialDualAnalogInV2(BrickletWithMCU):
148
151
  return await self.get_voltage(sid)
149
152
  return await self.get_all_voltages()
150
153
 
151
- 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
152
155
  self,
153
156
  sid: int,
154
157
  period: int = 0,
@@ -196,7 +199,7 @@ class BrickletIndustrialDualAnalogInV2(BrickletWithMCU):
196
199
  )
197
200
  return self.__value_to_si(unpack_payload(payload, "i"))
198
201
 
199
- 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
200
203
  self,
201
204
  channel: int,
202
205
  period: int = 0,
@@ -429,7 +432,7 @@ class BrickletIndustrialDualAnalogInV2(BrickletWithMCU):
429
432
 
430
433
  return LedConfig(unpack_payload(payload, "B"))
431
434
 
432
- 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
433
436
  self,
434
437
  channel: int,
435
438
  minimum: float | Decimal,
@@ -4,6 +4,7 @@ Module for the Tinkerforge Industrial PTC Bricklet
4
4
  implemented using Python asyncIO. It does the low-level communication with the Tinkerforge ip connection and also
5
5
  handles conversion of raw units to SI units.
6
6
  """
7
+
7
8
  from .bricklet_ptc_v2 import BrickletPtcV2
8
9
  from .devices import DeviceIdentifier
9
10
 
@@ -3,6 +3,7 @@ Module for the Tinkerforge IO-16 Bricklet (https://www.tinkerforge.com/en/doc/Ha
3
3
  implemented using Python asyncio. It does the low-level communication with the Tinkerforge ip connection and also
4
4
  handles conversion of raw units to SI units.
5
5
  """
6
+
6
7
  # pylint: disable=duplicate-code # Many sensors of different generations have a similar API
7
8
  from __future__ import annotations
8
9
 
@@ -209,7 +210,7 @@ class BrickletIO16(Device):
209
210
  )
210
211
  return unpack_payload(payload, "B")
211
212
 
212
- 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
213
214
  self,
214
215
  port: _Port | str,
215
216
  selection_mask: int,
@@ -277,7 +278,7 @@ class BrickletIO16(Device):
277
278
  )
278
279
  return GetPortConfiguration(*unpack_payload(payload, "B B"))
279
280
 
280
- 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
281
282
  self,
282
283
  sid: int,
283
284
  period: int = 0,
@@ -287,16 +288,16 @@ class BrickletIO16(Device):
287
288
  maximum: float | Decimal | None = None,
288
289
  response_expected: bool = True,
289
290
  ) -> None:
290
- port = Port.A if sid < 16 else Port.B
291
+ port = Port.A if sid < 8 else Port.B
291
292
  interrupt_mask = await self.get_port_interrupt(port)
292
- interrupt_mask &= ~(1 << (sid % 16)) # Reset the bit a position sid
293
- interrupt_mask |= int(bool(period)) << (sid % 16) # if period is non-zero, enable the interrupt
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
294
295
  await self.set_port_interrupt(port, interrupt_mask)
295
296
 
296
297
  async def get_callback_configuration(self, sid: int) -> AdvancedCallbackConfiguration:
297
- port = Port.A if sid < 16 else Port.B
298
+ port = Port.A if sid < 8 else Port.B
298
299
  interrupt_mask = await self.get_port_interrupt(port)
299
- value = interrupt_mask & (1 << (sid % 16))
300
+ value = interrupt_mask & (1 << (sid % 8))
300
301
  return AdvancedCallbackConfiguration(int(bool(value)), False, None, None, None)
301
302
 
302
303
  async def set_debounce_period(self, debounce_period: int = 100, response_expected: bool = True) -> None:
@@ -359,7 +360,7 @@ class BrickletIO16(Device):
359
360
  )
360
361
  return unpack_payload(payload, "B")
361
362
 
362
- 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
363
364
  self, port: _Port | str, selection_mask: int, value_mask: int, time: int, response_expected: bool = True
364
365
  ) -> None:
365
366
  """
@@ -445,7 +446,7 @@ class BrickletIO16(Device):
445
446
 
446
447
  .. versionadded:: 2.0.3$nbsp;(Plugin)
447
448
  """
448
- assert isinstance(pin, int) and (0 <= pin <= 7)
449
+ assert isinstance(pin, int) and (0 <= pin <= 1)
449
450
 
450
451
  _, payload = await self.ipcon.send_request(
451
452
  device=self,
@@ -496,7 +497,7 @@ class BrickletIO16(Device):
496
497
 
497
498
  .. versionadded:: 2.0.3$nbsp;(Plugin)
498
499
  """
499
- assert isinstance(pin, int) and (0 <= pin <= 7)
500
+ assert isinstance(pin, int) and (0 <= pin <= 1)
500
501
 
501
502
  _, payload = await self.ipcon.send_request(
502
503
  device=self,
@@ -3,12 +3,15 @@ Module for the Tinkerforge IO-4 Bricklet 2.0 (https://www.tinkerforge.com/en/doc
3
3
  implemented using Python asyncio. It does the low-level communication with the Tinkerforge ip connection and also
4
4
  handles conversion of raw units to SI units.
5
5
  """
6
+
6
7
  # pylint: disable=duplicate-code # Many sensors of different generations have a similar API
7
8
  from __future__ import annotations
8
9
 
10
+ import asyncio
11
+ from asyncio import CancelledError
9
12
  from decimal import Decimal
10
13
  from enum import Enum, unique
11
- from typing import TYPE_CHECKING, AsyncGenerator, NamedTuple
14
+ from typing import TYPE_CHECKING, AsyncGenerator, NamedTuple, TypeAlias, TypedDict
12
15
 
13
16
  from .devices import (
14
17
  AdvancedCallbackConfiguration,
@@ -18,11 +21,14 @@ from .devices import (
18
21
  SimpleCallbackConfiguration,
19
22
  )
20
23
  from .devices import ThresholdOption as Threshold
21
- from .devices import _FunctionID
24
+ from .devices import (
25
+ _FunctionID,
26
+ )
27
+ from .helper import join
22
28
  from .ip_connection_helper import pack_payload, unpack_payload
23
29
 
24
30
  if TYPE_CHECKING:
25
- from .ip_connection import IPConnectionAsync
31
+ from .ip_connection import HeaderPayload, IPConnectionAsync
26
32
 
27
33
 
28
34
  @unique
@@ -34,9 +40,10 @@ class CallbackID(Enum):
34
40
  INPUT_VALUE = 17
35
41
  ALL_INPUT_VALUE = 18
36
42
  MONOFLOP_DONE = 19
43
+ EDGE_COUNT = 20
37
44
 
38
45
 
39
- _CallbackID = CallbackID
46
+ _CallbackID: TypeAlias = CallbackID # pylint: disable=invalid-name
40
47
 
41
48
 
42
49
  @unique
@@ -90,6 +97,14 @@ class EdgeType(Enum):
90
97
  _EdgeType = EdgeType
91
98
 
92
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
+
93
108
  class GetConfiguration(NamedTuple):
94
109
  direction: Direction
95
110
  value: bool
@@ -116,7 +131,7 @@ class GetPWMConfiguration(NamedTuple):
116
131
  duty_cycle: Decimal
117
132
 
118
133
 
119
- class BrickletIO4V2(BrickletWithMCU):
134
+ class BrickletIO4V2(BrickletWithMCU): # pylint: disable=too-many-public-methods
120
135
  """
121
136
  4-channel digital input/output
122
137
  """
@@ -146,6 +161,17 @@ class BrickletIO4V2(BrickletWithMCU):
146
161
  super().__init__(self.DEVICE_DISPLAY_NAME, uid, ipcon)
147
162
 
148
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
+ }
149
175
 
150
176
  async def set_value(
151
177
  self, value: tuple[bool, bool, bool, bool] | list[bool], response_expected: bool = True
@@ -270,7 +296,7 @@ class BrickletIO4V2(BrickletWithMCU):
270
296
  direction = Direction(direction)
271
297
  return GetConfiguration(direction, value)
272
298
 
273
- 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
274
300
  self,
275
301
  sid: int,
276
302
  period: int = 0,
@@ -280,23 +306,32 @@ class BrickletIO4V2(BrickletWithMCU):
280
306
  maximum: float | Decimal | None = None,
281
307
  response_expected: bool = True,
282
308
  ) -> None:
283
- assert sid in range(5)
309
+ assert sid in range(4 + 1 + 4)
284
310
 
285
311
  if sid in range(4):
286
312
  await self.set_input_value_callback_configuration(sid, period, value_has_to_change, response_expected)
287
- else:
313
+ elif sid == 4:
288
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)
289
317
 
290
318
  async def get_callback_configuration(self, sid: int) -> AdvancedCallbackConfiguration:
291
- assert sid in range(5)
319
+ assert sid in range(4 + 1 + 4)
292
320
 
293
321
  if sid in range(4):
294
322
  return AdvancedCallbackConfiguration(
295
323
  *(await self.get_input_value_callback_configuration(sid)), option=None, minimum=None, maximum=None
296
324
  )
297
- return AdvancedCallbackConfiguration(
298
- *(await self.get_all_input_value_callback_configuration()), option=None, minimum=None, maximum=None
299
- )
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}")
300
335
 
301
336
  async def set_input_value_callback_configuration(
302
337
  self, channel: int, period: int = 0, value_has_to_change: bool = False, response_expected: bool = True
@@ -382,6 +417,53 @@ class BrickletIO4V2(BrickletWithMCU):
382
417
  )
383
418
  return SimpleCallbackConfiguration(*unpack_payload(payload, "I !"))
384
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
+
385
467
  async def set_monoflop(self, channel: int, value: bool, time: int, response_expected: bool = True) -> None:
386
468
  """
387
469
  The first parameter is the desired state of the channel (*true* means output *high*
@@ -573,21 +655,59 @@ class BrickletIO4V2(BrickletWithMCU):
573
655
  frequency, duty_cycle = unpack_payload(payload, "I H")
574
656
  return GetPWMConfiguration(Decimal(frequency) / 10, Decimal(duty_cycle) / 10000)
575
657
 
576
- async def read_events(
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(
577
687
  self,
578
- events: tuple[int | _CallbackID, ...] | list[int | _CallbackID] | None = None,
579
- sids: tuple[int, ...] | list[int] | None = None,
688
+ events: set[_CallbackID],
689
+ sids: tuple[int, ...] | list[int],
580
690
  ) -> AsyncGenerator[Event, None]:
581
- assert events is None or sids is None
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.
582
694
 
583
- registered_events = set()
584
- sids = tuple() if sids is None else sids
585
- if events:
586
- for event in events:
587
- registered_events.add(self.CallbackID(event))
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.
588
702
 
703
+ Yields
704
+ -------
705
+ Event
706
+ Events matching the desired sid/event filters
707
+
708
+ """
589
709
  if not events and not sids:
590
- registered_events = set(self.CALLBACK_FORMATS.keys())
710
+ return
591
711
 
592
712
  async for header, payload in super()._read_events():
593
713
  try:
@@ -598,19 +718,52 @@ class BrickletIO4V2(BrickletWithMCU):
598
718
 
599
719
  if function_id is CallbackID.INPUT_VALUE:
600
720
  sid, value_has_changed, value = unpack_payload(payload, self.CALLBACK_FORMATS[function_id])
601
- if function_id in registered_events or sid in sids:
721
+ if function_id in events or sid in sids:
602
722
  yield Event(self, sid, function_id, value, value_has_changed)
603
723
  continue
604
724
  elif function_id is CallbackID.MONOFLOP_DONE:
605
725
  sid, value = unpack_payload(payload, self.CALLBACK_FORMATS[function_id])
606
- if function_id in registered_events or sid in sids:
726
+ if function_id in events or sid in sids:
607
727
  yield Event(self, sid, function_id, value)
608
728
  continue
609
729
  else:
610
730
  changed_sids, values = unpack_payload(payload, self.CALLBACK_FORMATS[function_id])
611
- if function_id in registered_events:
731
+ if function_id in events:
612
732
  # Use a special sid for the CallbackID.ALL_INPUT_VALUE, because it returns a tuple
613
733
  yield Event(self, 4, function_id, values, changed_sids)
614
734
  else:
615
735
  for sid in sids:
616
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
@@ -3,6 +3,7 @@ Module for the Tinkerforge Isolator Bricklet
3
3
  (https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Isolator.html) implemented using Python asyncio. It does
4
4
  the low-level communication with the Tinkerforge ip connection.
5
5
  """
6
+
6
7
  # pylint: disable=duplicate-code # Many sensors of different generations have a similar API
7
8
  from __future__ import annotations
8
9
 
@@ -3,6 +3,7 @@ Module for the Tinkerforge Moisture Bricklet (https://www.tinkerforge.com/en/doc
3
3
  implemented using Python asyncio. It does the low-level communication with the Tinkerforge ip connection and also
4
4
  handles conversion of raw units to SI units.
5
5
  """
6
+
6
7
  # pylint: disable=duplicate-code # Many sensors of different generations have a similar API
7
8
  from __future__ import annotations
8
9
 
@@ -85,7 +86,7 @@ class BrickletMoisture(Device):
85
86
 
86
87
  return await self.get_moisture_value()
87
88
 
88
- 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
89
90
  self,
90
91
  sid: int,
91
92
  period: int = 0,
@@ -3,6 +3,7 @@ Module for the Tinkerforge Barometer Bricklet 2.0
3
3
  (https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Barometer_V2.html) implemented using Python asyncio. It does the
4
4
  low-level communication with the Tinkerforge ip connection and also handles conversion of raw units to SI units.
5
5
  """
6
+
6
7
  # pylint: disable=duplicate-code # Many sensors of different generations have a similar API
7
8
  from __future__ import annotations
8
9
 
@@ -3,6 +3,7 @@ Module for the Tinkerforge PTC Bricklet (https://www.tinkerforge.com/en/doc/Hard
3
3
  using Python asyncIO. It does the low-level communication with the Tinkerforge ip connection and also handles conversion
4
4
  of raw units to SI units.
5
5
  """
6
+
6
7
  # pylint: disable=duplicate-code # Many sensors of different generations have a similar API
7
8
  from __future__ import annotations
8
9
 
@@ -180,7 +181,7 @@ class BrickletPtc(Device): # pylint: disable=too-many-public-methods
180
181
  return await self.get_resistance()
181
182
  return await self.is_sensor_connected()
182
183
 
183
- 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
184
185
  self,
185
186
  sid: int,
186
187
  period: int = 0,
@@ -3,6 +3,7 @@ Module for the Tinkerforge PTC Bricklet 2.0 (https://www.tinkerforge.com/en/doc/
3
3
  implemented using Python asyncio. It does the low-level communication with the Tinkerforge ip connection and also
4
4
  handles conversion of raw units to SI units.
5
5
  """
6
+
6
7
  # pylint: disable=duplicate-code # Many sensors of different generations have a similar API
7
8
  from __future__ import annotations
8
9
 
@@ -177,7 +178,7 @@ class BrickletPtcV2(BrickletWithMCU):
177
178
  return await self.get_resistance()
178
179
  return await self.is_sensor_connected()
179
180
 
180
- 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
181
182
  self,
182
183
  sid: int,
183
184
  period: int = 0,
@@ -226,7 +227,7 @@ class BrickletPtcV2(BrickletWithMCU):
226
227
  )
227
228
  return self.__value_to_si_temperature(unpack_payload(payload, "i"))
228
229
 
229
- 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
230
231
  self,
231
232
  period: int = 0,
232
233
  value_has_to_change: bool = False,
@@ -312,7 +313,7 @@ class BrickletPtcV2(BrickletWithMCU):
312
313
  )
313
314
  return self.__value_to_si_resistance(unpack_payload(payload, "i"))
314
315
 
315
- 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
316
317
  self,
317
318
  period: int = 0,
318
319
  value_has_to_change: bool = False,
@@ -3,6 +3,7 @@ Module for the RS232 Bricklet 2.0 (https://www.tinkerforge.com/en/doc/Hardware/B
3
3
  using Python asyncIO. It does the low-level communication with the Tinkerforge ip connection and also handles conversion
4
4
  of raw units to SI units.
5
5
  """
6
+
6
7
  # pylint: disable=duplicate-code # Many sensors of different generations have a similar API
7
8
  from __future__ import annotations
8
9
 
@@ -261,7 +262,7 @@ class BrickletRS232V2(BrickletWithMCU):
261
262
 
262
263
  return unpack_payload(payload, "!")
263
264
 
264
- async def set_configuration( # pylint: disable=too-many-arguments
265
+ async def set_configuration( # pylint: disable=too-many-arguments,too-many-positional-arguments
265
266
  self,
266
267
  baudrate: int = 115200,
267
268
  parity: _Parity | int = Parity.NONE,
@@ -4,6 +4,7 @@ Module for the Segment Display 4x7 Bricklet
4
4
  does the low-level communication with the Tinkerforge ip connection and also handles conversion of raw units to SI
5
5
  units.
6
6
  """
7
+
7
8
  from __future__ import annotations
8
9
 
9
10
  from enum import Enum, unique
@@ -122,7 +123,7 @@ class BrickletSegmentDisplay4x7(Device):
122
123
  )
123
124
  return GetSegments(*unpack_payload(payload, "4B B !"))
124
125
 
125
- async def start_counter( # pylint: disable=too-many-arguments
126
+ async def start_counter( # pylint: disable=too-many-arguments,too-many-positional-arguments
126
127
  self, value_from: int, value_to: int, increment: int = 1, length: int = 1000, response_expected: bool = True
127
128
  ) -> None:
128
129
  """
@@ -4,6 +4,7 @@ Module for the Tinkerforge Segment Display 4x7 Bricklet 2.0
4
4
  does the low-level communication with the Tinkerforge ip connection and also handles conversion of raw units to SI
5
5
  units.
6
6
  """
7
+
7
8
  # pylint: disable=duplicate-code # Many sensors of different generations have a similar API
8
9
  from __future__ import annotations
9
10
 
@@ -203,7 +204,7 @@ class BrickletSegmentDisplay4x7V2(BrickletWithMCU):
203
204
 
204
205
  return unpack_payload(payload, "!")
205
206
 
206
- async def start_counter( # pylint: disable=too-many-arguments
207
+ async def start_counter( # pylint: disable=too-many-arguments,too-many-positional-arguments
207
208
  self, value_from: int, value_to: int, increment: int, length: int, response_expected: bool = True
208
209
  ) -> None:
209
210
  """
@@ -3,6 +3,7 @@ Module for the Tinkerforge Temperature Bricklet (https://www.tinkerforge.com/en/
3
3
  implemented using Python asyncIO. It does the low-level communication with the Tinkerforge ip connection and also
4
4
  handles conversion of raw units to SI units.
5
5
  """
6
+
6
7
  # pylint: disable=duplicate-code # Many sensors of different generations have a similar API
7
8
  from __future__ import annotations
8
9
 
@@ -101,7 +102,7 @@ class BrickletTemperature(Device):
101
102
 
102
103
  return await self.get_temperature()
103
104
 
104
- 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
105
106
  self,
106
107
  sid: int,
107
108
  period: int = 0,
@@ -3,6 +3,7 @@ Module for the Tinkerforge Temperature Bricklet 2.0
3
3
  (https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Temperature_V2.html) implemented using Python asyncio. It does
4
4
  the low-level communication with the Tinkerforge ip connection and also handles conversion of raw units to SI units.
5
5
  """
6
+
6
7
  # pylint: disable=duplicate-code # Many sensors of different generations have a similar API
7
8
  from __future__ import annotations
8
9
 
@@ -93,7 +94,7 @@ class BrickletTemperatureV2(BrickletWithMCU):
93
94
 
94
95
  return await self.get_temperature()
95
96
 
96
- 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
97
98
  self,
98
99
  sid: int,
99
100
  period: int = 0,
@@ -132,7 +133,7 @@ class BrickletTemperatureV2(BrickletWithMCU):
132
133
  )
133
134
  return self.__value_to_si(unpack_payload(payload, "h"))
134
135
 
135
- 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
136
137
  self,
137
138
  period: int = 0,
138
139
  value_has_to_change: bool = False,
@@ -3,6 +3,7 @@ Module for the Tinkerforge Thermocouple Bricklet 2.0
3
3
  (https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Thermocouple_V2.html) implemented using Python asyncio. It does
4
4
  the low-level communication with the Tinkerforge ip connection and also handles conversion of raw units to SI units.
5
5
  """
6
+
6
7
  # pylint: disable=duplicate-code # Many sensors of different generations have a similar API
7
8
  from __future__ import annotations
8
9
 
@@ -181,7 +182,7 @@ class BrickletThermocoupleV2(BrickletWithMCU):
181
182
  return await self.get_error_state()
182
183
  raise ValueError(f"Invalid sid: {sid}. sid must be in (0, 1).")
183
184
 
184
- 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
185
186
  self,
186
187
  sid: int,
187
188
  period: int = 0,
@@ -225,7 +226,7 @@ class BrickletThermocoupleV2(BrickletWithMCU):
225
226
  )
226
227
  return self.__value_to_si(unpack_payload(payload, "i"))
227
228
 
228
- 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
229
230
  self,
230
231
  period: int = 0,
231
232
  value_has_to_change: bool = False,
@@ -2,6 +2,7 @@
2
2
  The device factory which allows to create instances of Bricks and Bricklets from
3
3
  their device id
4
4
  """
5
+
5
6
  from __future__ import annotations
6
7
 
7
8
  from typing import TYPE_CHECKING
@@ -1,6 +1,7 @@
1
1
  """
2
2
  This file contains all base classes used by Bricks and bricklets
3
3
  """
4
+
4
5
  from __future__ import annotations
5
6
 
6
7
  import time
@@ -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
@@ -2,6 +2,7 @@
2
2
  This module implements the underlying ip connection to the Bricks and Bricklets.
3
3
  See https://www.tinkerforge.com/de/doc/Low_Level_Protocols/TCPIP.html for details.
4
4
  """
5
+
5
6
  from __future__ import annotations
6
7
 
7
8
  import asyncio
@@ -296,9 +297,11 @@ class IPConnectionAsync: # pylint: disable=too-many-instance-attributes
296
297
  # We will return None for all 'invalid' fields instead of garbage like the Tinkerforge API
297
298
  return EnumerationPayload(
298
299
  base58decode(uid),
299
- None
300
- if (enumeration_type is EnumerationType.DISCONNECTED or connected_uid == "0")
301
- else base58decode(connected_uid),
300
+ (
301
+ None
302
+ if (enumeration_type is EnumerationType.DISCONNECTED or connected_uid == "0")
303
+ else base58decode(connected_uid)
304
+ ),
302
305
  None if enumeration_type is EnumerationType.DISCONNECTED else position,
303
306
  None if enumeration_type is EnumerationType.DISCONNECTED else hardware_version,
304
307
  None if enumeration_type is EnumerationType.DISCONNECTED else firmware_version,
@@ -340,8 +343,7 @@ class IPConnectionAsync: # pylint: disable=too-many-instance-attributes
340
343
  data: bytes = b"",
341
344
  *,
342
345
  response_expected: Literal[True],
343
- ) -> tuple[HeaderPayload, bytes]:
344
- ...
346
+ ) -> tuple[HeaderPayload, bytes]: ...
345
347
 
346
348
  @overload
347
349
  async def send_request(
@@ -351,8 +353,7 @@ class IPConnectionAsync: # pylint: disable=too-many-instance-attributes
351
353
  data: bytes = b"",
352
354
  *,
353
355
  response_expected: Literal[False] = ...,
354
- ) -> None:
355
- ...
356
+ ) -> None: ...
356
357
 
357
358
  @overload
358
359
  async def send_request(
@@ -362,8 +363,7 @@ class IPConnectionAsync: # pylint: disable=too-many-instance-attributes
362
363
  data: bytes = b"",
363
364
  *,
364
365
  response_expected: bool = ...,
365
- ) -> tuple[HeaderPayload, bytes] | None:
366
- ...
366
+ ) -> tuple[HeaderPayload, bytes] | None: ...
367
367
 
368
368
  async def send_request(
369
369
  self,
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Some helper functions to encode and decode Tinkerforge protocol payloads.
3
3
  """
4
+
4
5
  from __future__ import annotations
5
6
 
6
7
  import math
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
2
- Name: tinkerforge_async
3
- Version: 1.5.2
1
+ Metadata-Version: 2.4
2
+ Name: tinkerforge-async
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
@@ -26,24 +24,25 @@ Classifier: Topic :: Scientific/Engineering
26
24
  Requires-Python: >=3.7
27
25
  Description-Content-Type: text/markdown
28
26
  License-File: LICENSE
29
- Requires-Dist: typing-extensions ; python_version < "3.11"
27
+ Requires-Dist: typing-extensions; python_version < "3.11"
30
28
  Provides-Extra: dev
31
- Requires-Dist: black ; extra == 'dev'
32
- Requires-Dist: build ; extra == 'dev'
33
- Requires-Dist: isort ; extra == 'dev'
34
- Requires-Dist: mypy ; extra == 'dev'
35
- Requires-Dist: pre-commit ; extra == 'dev'
36
- Requires-Dist: pylint ; extra == 'dev'
37
- Requires-Dist: setuptools ; extra == 'dev'
38
- Requires-Dist: twine ; extra == 'dev'
29
+ Requires-Dist: black; extra == "dev"
30
+ Requires-Dist: build; extra == "dev"
31
+ Requires-Dist: isort; extra == "dev"
32
+ Requires-Dist: mypy; extra == "dev"
33
+ Requires-Dist: pre-commit; extra == "dev"
34
+ Requires-Dist: pylint; extra == "dev"
35
+ Requires-Dist: setuptools; extra == "dev"
36
+ Requires-Dist: twine; extra == "dev"
39
37
  Provides-Extra: doc
40
- Requires-Dist: myst-parser ; extra == 'doc'
41
- Requires-Dist: sphinx ; extra == 'doc'
38
+ Requires-Dist: myst-parser; extra == "doc"
39
+ Requires-Dist: sphinx; extra == "doc"
42
40
  Provides-Extra: test
43
- Requires-Dist: mypy ; extra == 'test'
44
- Requires-Dist: pylint ; extra == 'test'
45
- Requires-Dist: pytest ; extra == 'test'
46
- Requires-Dist: setuptools ; extra == 'test'
41
+ Requires-Dist: mypy; extra == "test"
42
+ Requires-Dist: pylint; extra == "test"
43
+ Requires-Dist: pytest; extra == "test"
44
+ Requires-Dist: setuptools; extra == "test"
45
+ Dynamic: license-file
47
46
 
48
47
  [![pylint](../../actions/workflows/pylint.yml/badge.svg)](../../actions/workflows/pylint.yml)
49
48
  [![PyPI](https://img.shields.io/pypi/v/tinkerforge-async)](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.7+)
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
- - ### [IP Connection](https://www.tinkerforge.com/de/doc/Software/Bricklets/IO4V2_Bricklet_Python.html)
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 HZ and the duty cycle is normalized to 1.
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
 
@@ -0,0 +1,36 @@
1
+ tinkerforge_async/__init__.py,sha256=7R17QmN9c0bgTDxQedKy8gD_pyuai_ECssQ32HaUH6Q,377
2
+ tinkerforge_async/_version.py,sha256=ZJVmigCflF-sQaZSUHnTzabCteiDbDVsC3rFreEgPtQ,65
3
+ tinkerforge_async/async_event_bus.py,sha256=c1uFOL9JSFGk9Ii0NaR5s1YDNi3oPI89j969MsSNdd8,1805
4
+ tinkerforge_async/brick_master.py,sha256=OUHWYM0lxMKnvXaTgMahbxVSZaKVt3pbKOqbcmry6Bw,129818
5
+ tinkerforge_async/bricklet_ambient_light_v2.py,sha256=V2ziYe_L_i6LBdysA31-u2QxGDolR7Hwn_M6PMZHlHA,13433
6
+ tinkerforge_async/bricklet_ambient_light_v3.py,sha256=zRmJZEQf9_y1Tqlt1A33plIFL9Zi_V2e7DGGGldr0VI,12232
7
+ tinkerforge_async/bricklet_analog_in.py,sha256=xON8WCiqBjZpHTEt4kSv7sSEIXdejT6K5mI_SJ3ATM0,17185
8
+ tinkerforge_async/bricklet_barometer.py,sha256=1TXMv7GKYPusgcLKKuLl9TiiTn7g57-h6y2h-8lZGz0,19279
9
+ tinkerforge_async/bricklet_barometer_v2.py,sha256=NKmvALPYkGlidAmnPbfb5kKj4yOmxjGZqbv_rY5mLJ0,26688
10
+ tinkerforge_async/bricklet_humidity.py,sha256=UMscyxWoEgVH5crOBFqTvTMzLiFbNYJudpKjSnVKD3w,14979
11
+ tinkerforge_async/bricklet_humidity_v2.py,sha256=So1D_t7RuACsL3MgoVrvuAZjuCE0lKn5MJnZ20ZJCeU,19702
12
+ tinkerforge_async/bricklet_industrial_dual_analog_in_v2.py,sha256=9985a5UTd4rbVswu22naW_4aPWsEkz2_exZF2XPkQG0,20391
13
+ tinkerforge_async/bricklet_industrial_ptc.py,sha256=MfOj9jssaDAlC94o7ZVnK8hZPrUVavlXmMQ8bL2kblA,609
14
+ tinkerforge_async/bricklet_io16.py,sha256=5Ka9XOaaGnrFsMA7wduGU2okF2cV5rg6Io6iEXgZoE4,20961
15
+ tinkerforge_async/bricklet_io4_v2.py,sha256=4wkkKdxRFbf3jPeXJums2fPaETZHN8u05u6I3q47H-o,28266
16
+ tinkerforge_async/bricklet_isolator.py,sha256=JUejoYhlf0q9RYCVY00eKXJ0YEyfcG1N4HVbIz3YhlU,11160
17
+ tinkerforge_async/bricklet_moisture.py,sha256=G91T03pVhHMRAl8YWHT0fpdqFWBdVF1C0GtVuk1BWkM,10109
18
+ tinkerforge_async/bricklet_motion_detector_v2.py,sha256=hhKQ4MnQC_KI2TupYneDWTQvf1jYs4QeaEYj-JzCaE0,6452
19
+ tinkerforge_async/bricklet_ptc.py,sha256=8NhX8hNhpPVm1cK7Wzq-WveR8gd-w3sv0ydybE6UxF0,22190
20
+ tinkerforge_async/bricklet_ptc_v2.py,sha256=Kq6IQLJICyv7ThVz7HJpggWxLjH27pAbDG8FEvIidz4,22739
21
+ tinkerforge_async/bricklet_rs232_v2.py,sha256=SB5W-4YZkliAUUAtolwGh7Xd0TFmC1_tPkAJY90LlA8,18084
22
+ tinkerforge_async/bricklet_segment_display_4x7.py,sha256=n-LM7eoRBSLFkqoUuFjrp-NxynUTTjJYs6lpiz602-k,6435
23
+ tinkerforge_async/bricklet_segment_display_4x7_v2.py,sha256=GLypCSv-TGMD_98KV5bOTaUPEqOZ4CkB9gtaYUn0oCM,8933
24
+ tinkerforge_async/bricklet_temperature.py,sha256=erN1Vh9S3-octQDfMESdCWVvGxmYFzWZbeov02FIibo,11372
25
+ tinkerforge_async/bricklet_temperature_v2.py,sha256=xh_heEqNcZLjBS15m79yJCzRwcA6jzDMkMEI7Datpa4,9763
26
+ tinkerforge_async/bricklet_thermocouple_v2.py,sha256=6i3MmctMNnx26C691l9q5JPsu0SoeKneCkD1egwJkGI,15306
27
+ tinkerforge_async/device_factory.py,sha256=cJ4yL8vP580MywFu5-M_jk3m1EQe5erwCqMZDvntwGE,3370
28
+ tinkerforge_async/devices.py,sha256=6fNFoGbaaecf6It6rNoWuNu9Lvoyf-k1ngCdf2BU3vM,15635
29
+ tinkerforge_async/helper.py,sha256=ws_0Qn_pmB-nAJlSdQF4-T1DY8Z21n_bLQKkI2ZEMtQ,1365
30
+ tinkerforge_async/ip_connection.py,sha256=8pMJ4OkH-NLv06JBMSAkkbvsSThlx_cQm4RCmNjXiYk,27688
31
+ tinkerforge_async/ip_connection_helper.py,sha256=DIm4tb5ZoJfYehTLbxxMyNFut_O5t9WllIG4yxvdtXI,4306
32
+ tinkerforge_async-1.6.0.dist-info/licenses/LICENSE,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
33
+ tinkerforge_async-1.6.0.dist-info/METADATA,sha256=X1OaCiQODCohdukMA2kVrvGbqWOqkDcPAuCf3gEoHPA,16915
34
+ tinkerforge_async-1.6.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
35
+ tinkerforge_async-1.6.0.dist-info/top_level.txt,sha256=YuYlWDVtbFvjqm-GoyH2asasmmn-lH1KeKBBtA17QJ4,18
36
+ tinkerforge_async-1.6.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.1.0)
2
+ Generator: setuptools (78.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,35 +0,0 @@
1
- tinkerforge_async/__init__.py,sha256=wv8UTQrY0vlHwJEO-50PAeUt1cnrAdtSW-2by3CtaaE,376
2
- tinkerforge_async/_version.py,sha256=UqJ3HNCU2vsgoUrCIWF8t4wsYLyCQGZJ4mOgfolgaoU,65
3
- tinkerforge_async/async_event_bus.py,sha256=Ng1bNw4tfPZUSMBudy47rTxLqJF96qpTEJIzh1MCq44,1806
4
- tinkerforge_async/brick_master.py,sha256=kZDN_FzuYmGjaZvYFI2ba2Sfv1mwGoFx9ZayH1DJGqI,129607
5
- tinkerforge_async/bricklet_ambient_light_v2.py,sha256=6OVxGK8kBU_ZcRXa9iJH_B8GbZ74XGBB5ix7WquS8yw,13402
6
- tinkerforge_async/bricklet_ambient_light_v3.py,sha256=oJ9K9HEI5fX0Tz9YDkfjyiGLsVuguOT5ukhnLsULnto,12171
7
- tinkerforge_async/bricklet_analog_in.py,sha256=RwHj6VVg95OBbBt3xKTdxU_mCLI6ByUztPfTTyLPggs,17154
8
- tinkerforge_async/bricklet_barometer.py,sha256=tSlI4LuuQ_X0-RIqJdeke1XCryzJ7UAGhf9kJrB8RTU,19248
9
- tinkerforge_async/bricklet_barometer_v2.py,sha256=dO7SP67iASTZZ8pDSBprQTevpMDC8IFHY_MoL6-hfKk,26567
10
- tinkerforge_async/bricklet_humidity.py,sha256=_PVk3zUYr4o4o7Eyw2L7dLTS0alR9zrmXNMH2fPe6cE,14948
11
- tinkerforge_async/bricklet_humidity_v2.py,sha256=6JwWin22Kr_qtZ9-o7ioGpfk5LQcybHzq1LIahGpOb0,19611
12
- tinkerforge_async/bricklet_industrial_dual_analog_in_v2.py,sha256=nmkcYArdBXDO7Q6epGAMgGixlrT5kZIrMzlxddeAWGY,20291
13
- tinkerforge_async/bricklet_industrial_ptc.py,sha256=psGwgSArRgU-LgagUQVC8DIznHb1kmXSUNUG-1dfevI,608
14
- tinkerforge_async/bricklet_io16.py,sha256=bIraXe_vkJrmSlTV9wbSKDRUY4K1fGc8kCaR0PWaKj0,20875
15
- tinkerforge_async/bricklet_io4_v2.py,sha256=GYb2N44jVV_hvijJ_YPx2Vf0Td-oJzGNT53gI1mNv2U,21506
16
- tinkerforge_async/bricklet_isolator.py,sha256=miTYcDMzY6gQ8lNU8ZS6vcPs0HDr8JrJ0y1J7nKsJHs,11159
17
- tinkerforge_async/bricklet_moisture.py,sha256=ICnnwPAcWmFcOL73OGWYlLlnAxsr_g7RUe6eZUNDR5I,10078
18
- tinkerforge_async/bricklet_motion_detector_v2.py,sha256=nCbYQd4staw62_mYcUVF1qBhzG_04y0jbzXGOyLXcWQ,6451
19
- tinkerforge_async/bricklet_ptc.py,sha256=6tuVQvJVmM3LuRrvFJdDIXiNt-ArLeHQJkIqYuekqRY,22159
20
- tinkerforge_async/bricklet_ptc_v2.py,sha256=tsH3e_Ppi7XQvhXzQclLxdubw8aZwSnkB0mPHaAsRUo,22648
21
- tinkerforge_async/bricklet_rs232_v2.py,sha256=fsZ6SS5ZwJFUrQhXcKatvAki6Vni-ozz58zpri65ZRc,18053
22
- tinkerforge_async/bricklet_segment_display_4x7.py,sha256=kl_ctg86w2-uPhEgiraSbtIDS0PH854_9LdA48xrBiQ,6404
23
- tinkerforge_async/bricklet_segment_display_4x7_v2.py,sha256=T5g-voFLtLAOyWKn_TNuKDJVaG5vi_7eVCNvkE5ziIs,8902
24
- tinkerforge_async/bricklet_temperature.py,sha256=wsaI5vq50d7X_FonRZfxpjtNOVM8tdqA74MPVrts8h4,11341
25
- tinkerforge_async/bricklet_temperature_v2.py,sha256=uYSnfW1Hr1WxY5M7kVahtpaQEK5XvdIhM_HhdJdSc-g,9702
26
- tinkerforge_async/bricklet_thermocouple_v2.py,sha256=KoVu6E3ZpXqR2aLMktepZVD86q0CQFYlGxUmBkVZO7o,15245
27
- tinkerforge_async/device_factory.py,sha256=UkK8mU-UN3bBPI9Z8kRpbUslxwGbUiGglFnGRyg6c9o,3369
28
- tinkerforge_async/devices.py,sha256=XQezaYuiH25MX8rD7sVMdfERYhDlvUg8x1jhj3xNsKI,15634
29
- tinkerforge_async/ip_connection.py,sha256=KPAFGTysuCj8uVWMgVUDvP_zPOpjeYOKVb16SDLRcjE,27671
30
- tinkerforge_async/ip_connection_helper.py,sha256=kt4JhONMxJdN4upIpVZlqTKmQcSyG2zXkmnCC2QL91Y,4305
31
- tinkerforge_async-1.5.2.dist-info/LICENSE,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
32
- tinkerforge_async-1.5.2.dist-info/METADATA,sha256=eUWus5K4ai4ueovreuHwyyy4TrTtBrBplXbE22D_C2w,16699
33
- tinkerforge_async-1.5.2.dist-info/WHEEL,sha256=cpQTJ5IWu9CdaPViMhC9YzF8gZuS5-vlfoFihTBC86A,91
34
- tinkerforge_async-1.5.2.dist-info/top_level.txt,sha256=YuYlWDVtbFvjqm-GoyH2asasmmn-lH1KeKBBtA17QJ4,18
35
- tinkerforge_async-1.5.2.dist-info/RECORD,,