Skip to main content

Python3 AsyncIO Tinkerforge driver

Project description

pylint PyPI PyPI - Python Version PyPI - Status License: GPL v3 code style

TinkerforgeAsync

This is a reimplementation of the Tinkerforge Python bindings (original Python bindings) using Python 3 asyncio. The original bindings used threads to manage the blocking operations. A much cleaner implementation is possible using the await syntax from asyncio.

Note: This API implementation is not an official Tinkerforge implementation. I am in no way affiliated with the Tinkerforge GmbH. Use at your own risk. If you find any bugs, please report them.

The library is fully type-hinted.

Supported Bricks/Bricklets

Brick Supported Tested Comments
Master :heavy_check_mark: :heavy_check_mark:
Bricklet Supported Tested
Ambient Light 2.0 :heavy_check_mark: :heavy_check_mark:
Ambient Light 3.0 :heavy_check_mark: :heavy_check_mark:
Analog In :heavy_check_mark: :heavy_check_mark:
Barometer :heavy_check_mark: :heavy_check_mark:
Barometer 2.0 :heavy_check_mark: :heavy_check_mark:
Humidity :heavy_check_mark: :heavy_check_mark:
Humidity 2.0 :heavy_check_mark: :heavy_check_mark:
Industrial Dual Analog In 2.0 :heavy_check_mark: :heavy_check_mark:
Industrial PTC :heavy_check_mark: :heavy_check_mark:
IO-4 2.0 :heavy_check_mark: :heavy_check_mark:
IO-16 :heavy_check_mark: :heavy_check_mark:
Isolator :heavy_check_mark: :heavy_check_mark:
Moisture :heavy_check_mark: :heavy_check_mark:
Motion Detector 2.0 :heavy_check_mark: :heavy_check_mark:
PTC :heavy_check_mark: :heavy_check_mark:
PTC 2.0 :heavy_check_mark: :heavy_check_mark:
RS232 2.0 :heavy_check_mark: :heavy_check_mark:
Segment Display 4x7 :heavy_check_mark: :heavy_check_mark:
Segment Display 4x7 2.0 :heavy_check_mark: :heavy_check_mark:
Temperature :heavy_check_mark: :heavy_check_mark:
Temperature 2.0 :heavy_check_mark: :heavy_check_mark:
Thermocouple 2.0 :heavy_check_mark: :heavy_check_mark:

Documentation

The documentation is currently work in progress. The full documentation will be moved to https://patrickbaus.github.io/tinkerforge_async/. Below you can find the current state of the documentation. I use the Numpydoc style for documentation and Sphinx for compiling it.

Setup

To install the library in a virtual environment (always use venvs with every project):

python3 -m venv env  # virtual environment, optional
source env/bin/activate  # only if the virtual environment is used
pip install tinkerforge-async

Changes made to the API

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:

Design Changes

  • Only Python 3 is supported (3.7+)

  • Replaced threads with an async event loop

  • 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.

    Old style:

    bricklet = BrickletHumidity(UID, ipcon)
    bricklet.set_response_expected(
        BrickletHumidity.FUNCTION_SET_HUMIDITY_CALLBACK_PERIOD, True
    )
    bricklet.set_humidity_callback_period(1000)
    

    New style:

    bricklet = BrickletHumidity(UID, ipcon)
    await bricklet.set_humidity_callback_period(
        1000, response_expected=True
    )  # Raises an exception if unsuccessful
    
  • Replaced all constants with Enums and enforced their use using assertions. This will allow beginners to spot their mistakes earlier and make the code more readable, including any debug output statements.

    Old style:

    class BrickletHumidity(Device):
        FUNCTION_GET_HUMIDITY = 1
        FUNCTION_GET_ANALOG_VALUE = 2
        FUNCTION_SET_HUMIDITY_CALLBACK_PERIOD = 3
        FUNCTION_GET_HUMIDITY_CALLBACK_PERIOD = 4
        FUNCTION_SET_ANALOG_VALUE_CALLBACK_PERIOD = 5
        FUNCTION_GET_ANALOG_VALUE_CALLBACK_PERIOD = 6
        FUNCTION_SET_HUMIDITY_CALLBACK_THRESHOLD = 7
        FUNCTION_GET_HUMIDITY_CALLBACK_THRESHOLD = 8
        FUNCTION_SET_ANALOG_VALUE_CALLBACK_THRESHOLD = 9
        FUNCTION_GET_ANALOG_VALUE_CALLBACK_THRESHOLD = 10
        FUNCTION_SET_DEBOUNCE_PERIOD = 11
        FUNCTION_GET_DEBOUNCE_PERIOD = 12
        FUNCTION_GET_IDENTITY = 255
    

    New style:

    class BrickletHumidity(Device):
        @unique
        class FunctionID(Enum):
            GET_HUMIDITY = 1
            GET_ANALOG_VALUE = 2
            SET_HUMIDITY_CALLBACK_PERIOD = 3
            GET_HUMIDITY_CALLBACK_PERIOD = 4
            SET_ANALOG_VALUE_CALLBACK_PERIOD = 5
            GET_ANALOG_VALUE_CALLBACK_PERIOD = 6
            SET_HUMIDITY_CALLBACK_THRESHOLD = 7
            GET_HUMIDITY_CALLBACK_THRESHOLD = 8
            SET_ANALOG_VALUE_CALLBACK_THRESHOLD = 9
            GET_ANALOG_VALUE_CALLBACK_THRESHOLD = 10
            SET_DEBOUNCE_PERIOD = 11
            GET_DEBOUNCE_PERIOD = 12
    
  • Moved from base58 encoded uids to integers.

  • Moved from callbacks to queues in order to keep users out of the callback hell. It makes the code style more readable when using the await syntax anyway.

  • Payloads will now be decoded by the Device object and no longer by the ip_connection. This makes the code a lot more readable. To do so, the payload and decoded header will be handed to the device. It will then decode it, if possible, and pass it on to the queue.

  • If physical quantities are measured we will now return standard SI units, not some unexpected stuff like centi °C (Temperature Bricklet). To preserve the precision the Decimal package is used. The only exception to this rule is the use of °C for temperature. This is for convenience.

  • All callbacks now contain a timestamp (Unix timestamp) and the device object.

    Example:

     Event(timestamp=1658756708.6839857, sender=Temperature Bricklet 2.0 with uid 161085 connected at IPConnectionAsync(192.168.1.164:4223), sid=0, function_id=CallbackID.TEMPERATURE, payload=305.46)
    
  • Added the concept of secondary ids (sid). By default, the secondary id is 0. If there is more than one sensor on the bricklet, they will have a sid value of 1,2, etc. This is especially useful for sensors like the Industrial Dual Analog In Bricklet 2.0, which returns its two channels via the same callback.

  • New functions:

    BrickMaster.set_wpa_enterprise_username(username): Set the WPA enterprise username without calling BrickMaster.set_wifi_certificate(). Takes a string instead of an array of int. BrickMaster.set_wpa_enterprise_password(password): Set the WPA enterprise password without calling BrickMaster.set_wifi_certificate(). Takes a string instead of an array of int. BrickMaster.get_wpa_enterprise_username(): Get the WPA enterprise password without calling BrickMaster.get_wifi_certificate(). Also returns a string instead of an array of int. BrickMaster.get_wpa_enterprise_password(): Get the WPA enterprise password without calling BrickMaster.get_wifi_certificate(). Also returns a string instead of an array of int.

  • IP Connection

    • IPConnection.authenticate(secret): removed. This can now be done through connect()
    • IPConnection.set_timeout/IPConnection.get_timeout: Replaced by a property
    • IPConnection.register_callback(callback_id, function): Replaced by register_event_queue()
    • IPConnection.connect(host, port=4223, authentication_secret=''): If authentication_secret is not empty, try to authenticate.
  • IP Connection

    • 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].
    • BrickletIO4V2.get_pwm_configuration() will return the frequency in units of HZ and the duty cycle is normalized to 1.
  • Master Brick

    • BrickMaster.set_wifi_configuration()/BrickMaster.get_wifi_configuration() will take/return all ips in natural order
    • BrickMaster.set_ethernet_configuration()/BrickMaster.get_ethernet_configuration() will take/return all ips in natural order
    • BrickMaster.write_wifi2_serial_port() will only accept a bytestring and no length argument. The length will be automatically determined from the string.
    • BrickMaster.set_wifi2_status_led(enabled) added. This allows setting the status led by value instead of calling enable_wifi2_status_led/disable_wifi2_status_led
  • PTC Bricklet

    • BrickletPtc() takes an additional parameter to define the type of sensor. The options are BrickletPtc.SensorType.PT_100 and BrickletPtc.SensorType.PT_1000. This only determines the resistance returned by the bricklet. The default is BrickletPtc.SensorType.PT_100.
    • BrickletPtc.sensor_type getter and setter to change the type of sensor used.
  • PTC Bricklet 2.0

    • BrickletPtcV2() takes an additional parameter to define the type of sensor. The options are BrickletPtc.SensorType.PT_100 and BrickletPtc.SensorType.PT_1000. This only determines the resistance returned by the bricklet. The default is BrickletPtc.SensorType.PT_100.
    • BrickletPtcV2.sensor_type getter and setter to change the type of sensor used.
  • Thermocouple Bricklet 2.0

    • 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.
    • BrickletThermocoupleV2.sensor_type getter and setter to change the type of sensor used.
  • Segment Display 4x7 Bricklet 2.0

    • 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.

Setup

There are currently no packages available at the PyPi repository. To install the module, clone the repository and run:

python3 -m venv env  # virtual environment, optional
source env/bin/activate  # only if the virtual environment is used
python3 setup.py install

Versioning

I use SemVer for versioning. For the versions available, see the tags on this repository.

Authors

License

This project is licensed under the GPL v3 license - see the LICENSE file for details

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tinkerforge_async-1.5.3.tar.gz (95.6 kB view details)

Uploaded Source

Built Distribution

tinkerforge_async-1.5.3-py3-none-any.whl (137.1 kB view details)

Uploaded Python 3

File details

Details for the file tinkerforge_async-1.5.3.tar.gz.

File metadata

  • Download URL: tinkerforge_async-1.5.3.tar.gz
  • Upload date:
  • Size: 95.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.0 CPython/3.12.4

File hashes

Hashes for tinkerforge_async-1.5.3.tar.gz
Algorithm Hash digest
SHA256 ccae473f2841f6db74e863f4849f029f380ad5b8022a8742ebd55e6c510edb23
MD5 5876a0c58c7669529dd2b836d443cc19
BLAKE2b-256 429cd199a595268b3e576b9db7eeded0435f13621f54a8f44efe2e96178ca2e0

See more details on using hashes here.

File details

Details for the file tinkerforge_async-1.5.3-py3-none-any.whl.

File metadata

File hashes

Hashes for tinkerforge_async-1.5.3-py3-none-any.whl
Algorithm Hash digest
SHA256 1c62629428d9aff5022a26e01cc2b9b543a79c017b5505f087a123e81df75488
MD5 d01f6e0afddcfe94934842f61675c00e
BLAKE2b-256 6e80c9f17de5a2438f9bd94f140cb201ca04552ea8169435600ad2ab61da0d90

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page