Skip to content

Commit

Permalink
Merge pull request #4 from PatrickBaus/add_isolator_bricklet
Browse files Browse the repository at this point in the history
Add isolator bricklet
  • Loading branch information
PatrickBaus authored Jun 18, 2024
2 parents 06d6b3e + b340e84 commit d9f6b16
Show file tree
Hide file tree
Showing 13 changed files with 497 additions and 53 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:

strategy:
matrix:
python-version: [ "3.10" ]
python-version: [ "3.12" ]

steps:
- name: Checkout source repository
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:

strategy:
matrix:
python-version: [ "3.10" ]
python-version: [ "3.12" ]

steps:
- name: Checkout source repository
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-test-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:

strategy:
matrix:
python-version: [ "3.10" ]
python-version: [ "3.12" ]

steps:
- name: Checkout source repository
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pylint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:

strategy:
matrix:
python-version: [ "3.10", "3.11" ]
python-version: [ "3.10", "3.11", "3.12" ]

steps:
- name: Checkout source repository
Expand Down
45 changes: 23 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,29 @@ The library is fully type-hinted.
|--|--|--|--|
|[Master](https://www.tinkerforge.com/en/doc/Hardware/Bricks/Master_Brick.html)|:heavy_check_mark:|:heavy_check_mark:| |

|Bricklet|Supported|Tested|
|--|--|--|
|[Ambient Light 2.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Ambient_Light_V2.html)|:heavy_check_mark:|:heavy_check_mark:|
|[Ambient Light 3.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Ambient_Light_V3.html)|:heavy_check_mark:|:heavy_check_mark:|
|[Analog In](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Analog_In.html)|:heavy_check_mark:|:heavy_check_mark:|
|[Barometer](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Barometer.html)|:heavy_check_mark:|:heavy_check_mark:|
|[Barometer 2.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Barometer_V2.html)|:heavy_check_mark:|:heavy_check_mark:|
|[Humidity](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Humidity.html)|:heavy_check_mark:|:heavy_check_mark:|
|[Humidity 2.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Humidity_V2.html)|:heavy_check_mark:|:heavy_check_mark:|
|[Industrial Dual Analog In Bricklet 2.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Industrial_Dual_Analog_In_V2.html)|:heavy_check_mark:|:heavy_check_mark:|
|[Industrial PTC](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Industrial_PTC.html)|:heavy_check_mark:|:heavy_check_mark:|
|[IO-4 2.0](https://www.tinkerforge.com/de/doc/Hardware/Bricklets/IO4_V2.html)|:heavy_check_mark:|:heavy_check_mark:|
|[IO-16](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/IO16.html)|:heavy_check_mark:|:heavy_check_mark:|
|[Moisture](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Moisture.html)|:heavy_check_mark:|:heavy_check_mark:|
|[Motion Detector 2.0](https://www.tinkerforge.com/de/doc/Hardware/Bricklets/Motion_Detector_V2.html)|:heavy_check_mark:|:heavy_check_mark:|
|[PTC Bricklet](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/PTC.html)|:heavy_check_mark:|:heavy_check_mark:|
|[PTC Bricklet 2.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/PTC_V2.html)|:heavy_check_mark:|:heavy_check_mark:|
|[RS232 Bricklet 2.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/RS232_V2.html)|:heavy_check_mark:|:heavy_check_mark:|
|[Segment Display 4x7 Bricklet](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Segment_Display_4x7.html)|:heavy_check_mark:|:heavy_check_mark:|
|[Segment Display 4x7 Bricklet 2.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Segment_Display_4x7_V2.html)|:heavy_check_mark:|:heavy_check_mark:|
|[Temperature](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Temperature.html)|:heavy_check_mark:|:heavy_check_mark:|
|[Temperature 2.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Temperature_V2.html)|:heavy_check_mark:|:heavy_check_mark:|
| Bricklet |Supported|Tested|
|--------------------------------------------------------------------------------------------------------------------------|--|--|
| [Ambient Light 2.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Ambient_Light_V2.html) |:heavy_check_mark:|:heavy_check_mark:|
| [Ambient Light 3.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Ambient_Light_V3.html) |:heavy_check_mark:|:heavy_check_mark:|
| [Analog In](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Analog_In.html) |:heavy_check_mark:|:heavy_check_mark:|
| [Barometer](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Barometer.html) |:heavy_check_mark:|:heavy_check_mark:|
| [Barometer 2.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Barometer_V2.html) |:heavy_check_mark:|:heavy_check_mark:|
| [Humidity](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Humidity.html) |:heavy_check_mark:|:heavy_check_mark:|
| [Humidity 2.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Humidity_V2.html) |:heavy_check_mark:|:heavy_check_mark:|
| [Industrial Dual Analog In 2.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Industrial_Dual_Analog_In_V2.html) |:heavy_check_mark:|:heavy_check_mark:|
| [Industrial PTC](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Industrial_PTC.html) |:heavy_check_mark:|:heavy_check_mark:|
| [IO-4 2.0](https://www.tinkerforge.com/de/doc/Hardware/Bricklets/IO4_V2.html) |:heavy_check_mark:|:heavy_check_mark:|
| [IO-16](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/IO16.html) |:heavy_check_mark:|:heavy_check_mark:|
| [Isolator](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Isolator.html) |:heavy_check_mark:|:heavy_check_mark:|
| [Moisture](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Moisture.html) |:heavy_check_mark:|:heavy_check_mark:|
| [Motion Detector 2.0](https://www.tinkerforge.com/de/doc/Hardware/Bricklets/Motion_Detector_V2.html) |:heavy_check_mark:|:heavy_check_mark:|
| [PTC](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/PTC.html) |:heavy_check_mark:|:heavy_check_mark:|
| [PTC 2.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/PTC_V2.html) |:heavy_check_mark:|:heavy_check_mark:|
| [RS232 2.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/RS232_V2.html) |:heavy_check_mark:|:heavy_check_mark:|
| [Segment Display 4x7](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Segment_Display_4x7.html) |:heavy_check_mark:|:heavy_check_mark:|
| [Segment Display 4x7 2.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Segment_Display_4x7_V2.html) |:heavy_check_mark:|:heavy_check_mark:|
| [Temperature](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Temperature.html) |:heavy_check_mark:|:heavy_check_mark:|
| [Temperature 2.0](https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Temperature_V2.html) |:heavy_check_mark:|:heavy_check_mark:|

## Documentation
The documentation is currently work in progress. The full documentation will be moved to
Expand Down
125 changes: 125 additions & 0 deletions examples/bricklet_isolator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#!/usr/bin/env python3
# pylint: disable=duplicate-code
"""
An example to demonstrate most of the capabilities of the Tinkerforge Isolator Bricklet.
"""
import asyncio
import warnings
from decimal import Decimal

from tinkerforge_async.bricklet_isolator import BrickletIsolator
from tinkerforge_async.devices import BrickletWithMCU
from tinkerforge_async.ip_connection import IPConnectionAsync


async def process_callbacks(device: BrickletIsolator) -> None:
"""Prints the callbacks (filtered by id) of the bricklet."""
async for packet in device.read_events():
print("Callback received", packet)


async def run_example_generic(bricklet: BrickletWithMCU) -> None:
"""This is a demo of the generic features of the Tinkerforge bricklets with a microcontroller."""
uid = await bricklet.read_uid()
print("Device uid:", uid)
await bricklet.write_uid(uid)

print("SPI error count:", await bricklet.get_spitfp_error_count())

print("Current bootloader mode:", await bricklet.get_bootloader_mode())
bootloader_mode = bricklet.BootloaderMode.FIRMWARE
print("Setting bootloader mode to", bootloader_mode, ":", await bricklet.set_bootloader_mode(bootloader_mode))

print("Disable status LED")
await bricklet.set_status_led_config(bricklet.LedConfig.OFF)
print("Current status:", await bricklet.get_status_led_config())
await asyncio.sleep(1)
print("Enable status LED")
await bricklet.set_status_led_config(bricklet.LedConfig.SHOW_STATUS)
print("Current status:", await bricklet.get_status_led_config())

print("Get Chip temperature:", await bricklet.get_chip_temperature() - Decimal("273.15"), "°C")

print("Reset Bricklet")
await bricklet.reset()


async def run_example(bricklet: BrickletIsolator) -> None:
"""This is the actual demo. If the bricklet is found, this code will be run."""
callback_task = asyncio.create_task(process_callbacks(bricklet))
try:
print("Identity:", await bricklet.get_identity())

print("Get isolator statistics:", await bricklet.get_statistics())

# Query a value
baud_rate = await bricklet.get_spitfp_baudrate()
print("Set SPITFP baud rate to 400000 baud.")
await bricklet.set_spitfp_baudrate(400000)
print("Get SPITFP baud rate:", await bricklet.get_spitfp_baudrate(), "baud")
await bricklet.set_spitfp_baudrate(baud_rate)
baud_rate_config = await bricklet.get_spitfp_baudrate_config()
print("Get SPITFP baud rate config:", baud_rate_config)
print("Set SPITFP baud rate config:", baud_rate_config)
await bricklet.set_spitfp_baudrate_config(*baud_rate_config)

# Use a configuration callback
print("Set callback period to", 1000, "ms and wait for callbacks.")
# We use a low humidity value on purpose, so that the callback will be triggered
await bricklet.set_statistics_callback_configuration(period=1000, value_has_to_change=False)
print("Configuration callback configuration:", await bricklet.get_statistics_callback_configuration())
await asyncio.sleep(2.1) # Wait for 2-3 callbacks
print("Disable configuration callback")
await bricklet.set_statistics_callback_configuration()
print("Configuration callback configuration:", await bricklet.get_statistics_callback_configuration())
# Test the generic features of the bricklet. These are available with all
# new bricklets that have a microcontroller
await run_example_generic(bricklet)
finally:
callback_task.cancel()


async def shutdown(tasks: set[asyncio.Task]) -> None:
"""Clean up by stopping all consumers"""
for task in tasks:
task.cancel()
await asyncio.gather(*tasks)


async def main() -> None:
"""
The main loop, that will spawn all callback handlers and wait until they are done. There are two callback handlers,
one waits for the bricklet to connect and runs the demo, the other handles messages sent by the bricklet.
"""
tasks = set()
try:
# Use the context manager of the ip connection. It will automatically do the cleanup.
async with IPConnectionAsync(host="127.0.0.1", port=4223) as connection:
await connection.enumerate()
# Read all enumeration replies, then start the example if we find the correct device
async for enumeration_type, device in connection.read_enumeration(): # pylint: disable=unused-variable
if isinstance(device, BrickletIsolator):
print(f"Found {device}, running example.")
tasks.add(asyncio.create_task(run_example(device)))
break
print(f"Found {device}, but not interested.")

# Wait for run_example() to finish
await asyncio.gather(*tasks)
except ConnectionRefusedError:
print("Could not connect to server. Connection refused. Is the brick daemon up?")
except asyncio.CancelledError:
print("Stopped the main loop.")
raise # It is good practice to re-raise CancelledErrors
finally:
await shutdown(tasks)


# Report all mistakes managing asynchronous resources.
warnings.simplefilter("always", ResourceWarning)

# Start the main loop and run the async loop forever. Turn off the debug parameter for production code.
try:
asyncio.run(main(), debug=True)
except KeyboardInterrupt:
print("Shutting down gracefully.")
7 changes: 1 addition & 6 deletions tinkerforge_async/brick_master.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

from .devices import BasicCallbackConfiguration
from .devices import BrickletPort as Port
from .devices import DeviceIdentifier, DeviceWithMCU, Event, GetSPITFPErrorCount
from .devices import DeviceIdentifier, DeviceWithMCU, Event, GetSPITFPBaudrateConfig, GetSPITFPErrorCount
from .devices import ThresholdOption as Threshold
from .devices import _FunctionID
from .ip_connection_helper import pack_payload, unpack_payload
Expand Down Expand Up @@ -265,11 +265,6 @@ class GetWifi2MeshAPStatus(NamedTuple):
mac_address: tuple[int, int, int, int, int, int]


class GetSPITFPBaudrateConfig(NamedTuple):
enable_dynamic_baudrate: bool
minimum_dynamic_baudrate: int


class GetProtocol1BrickletName(NamedTuple):
protocol_version: int
firmware_version: tuple[int, int, int]
Expand Down
18 changes: 10 additions & 8 deletions tinkerforge_async/bricklet_industrial_dual_analog_in_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@
from enum import Enum, unique
from typing import TYPE_CHECKING, AsyncGenerator, NamedTuple

from .devices import AdvancedCallbackConfiguration, BrickletWithMCU, DeviceIdentifier, Event, LedConfig
from .devices import (
AdvancedCallbackConfiguration,
BrickletWithMCU,
DeviceIdentifier,
Event,
LedConfig,
SimpleCallbackConfiguration,
)
from .devices import ThresholdOption as Threshold
from .devices import _FunctionID
from .ip_connection_helper import pack_payload, unpack_payload
Expand Down Expand Up @@ -99,11 +106,6 @@ class GetChannelLEDStatusConfig(NamedTuple):
config: ChannelLedStatusConfig


class GetAllVoltagesCallbackConfiguration(NamedTuple):
period: int
value_has_to_change: bool


class BrickletIndustrialDualAnalogInV2(BrickletWithMCU):
"""
Measures two DC voltages between -35V and +35V with 24bit resolution each
Expand Down Expand Up @@ -313,7 +315,7 @@ async def set_all_voltages_callback_configuration(
response_expected=response_expected,
)

async def get_all_voltages_callback_configuration(self) -> GetAllVoltagesCallbackConfiguration:
async def get_all_voltages_callback_configuration(self) -> SimpleCallbackConfiguration:
"""
Returns the callback configuration as set by :func:`Set All Voltages Callback Configuration`.
Expand All @@ -322,7 +324,7 @@ async def get_all_voltages_callback_configuration(self) -> GetAllVoltagesCallbac
_, payload = await self.ipcon.send_request(
device=self, function_id=FunctionID.GET_VOLTAGE_CALLBACK_CONFIGURATION, response_expected=True
)
return GetAllVoltagesCallbackConfiguration(*unpack_payload(payload, "I !"))
return SimpleCallbackConfiguration(*unpack_payload(payload, "I !"))

async def set_sample_rate(self, rate: _SamplingRate | int, response_expected: bool = True) -> None:
"""
Expand Down
21 changes: 11 additions & 10 deletions tinkerforge_async/bricklet_io4_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@
from enum import Enum, unique
from typing import TYPE_CHECKING, AsyncGenerator, NamedTuple

from .devices import AdvancedCallbackConfiguration, BrickletWithMCU, DeviceIdentifier, Event
from .devices import (
AdvancedCallbackConfiguration,
BrickletWithMCU,
DeviceIdentifier,
Event,
SimpleCallbackConfiguration,
)
from .devices import ThresholdOption as Threshold
from .devices import _FunctionID
from .ip_connection_helper import pack_payload, unpack_payload
Expand Down Expand Up @@ -94,11 +100,6 @@ class GetInputValueCallbackConfiguration(NamedTuple):
value_has_to_change: bool


class GetAllInputValueCallbackConfiguration(NamedTuple):
period: int
value_has_to_change: bool


class GetMonoflop(NamedTuple):
value: bool
time: int
Expand Down Expand Up @@ -329,7 +330,7 @@ async def set_input_value_callback_configuration(
response_expected=response_expected,
)

async def get_input_value_callback_configuration(self, channel: int) -> GetInputValueCallbackConfiguration:
async def get_input_value_callback_configuration(self, channel: int) -> SimpleCallbackConfiguration:
"""
Returns the callback configuration for the given channel as set by
:func:`Set Input Value Callback Configuration`.
Expand All @@ -342,7 +343,7 @@ async def get_input_value_callback_configuration(self, channel: int) -> GetInput
data=pack_payload((int(channel),), "B"),
response_expected=True,
)
return GetInputValueCallbackConfiguration(*unpack_payload(payload, "I !"))
return SimpleCallbackConfiguration(*unpack_payload(payload, "I !"))

async def set_all_input_value_callback_configuration(
self, period: int = 0, value_has_to_change: bool = False, response_expected: bool = True
Expand Down Expand Up @@ -371,15 +372,15 @@ async def set_all_input_value_callback_configuration(
response_expected=response_expected,
)

async def get_all_input_value_callback_configuration(self) -> GetAllInputValueCallbackConfiguration:
async def get_all_input_value_callback_configuration(self) -> SimpleCallbackConfiguration:
"""
Returns the callback configuration as set by
:func:`Set All Input Value Callback Configuration`.
"""
_, payload = await self.ipcon.send_request(
device=self, function_id=FunctionID.GET_ALL_INPUT_VALUE_CALLBACK_CONFIGURATION, response_expected=True
)
return GetAllInputValueCallbackConfiguration(*unpack_payload(payload, "I !"))
return SimpleCallbackConfiguration(*unpack_payload(payload, "I !"))

async def set_monoflop(self, channel: int, value: bool, time: int, response_expected: bool = True) -> None:
"""
Expand Down
Loading

0 comments on commit d9f6b16

Please sign in to comment.