Skip to main content

A python3 KNX stack for USB HID and KNXnet IP

Project description

knx-stack

Build Status codecov Documentation Status

A Python 3 KNX stack, not complete but easily extensible.

It is able to encode/decode knx messages for both USB HID and KNXnet IP.

It can be used with an asynchronous or synchronous client.

Examples

Setup

    >>> import knx_stack
    >>> individual_address = knx_stack.Address(0x0001)
    >>> abcd = knx_stack.GroupAddress(free_style=0xABCD)
    >>> abce = knx_stack.GroupAddress(three_level_style=knx_stack.address.ThreeLevelStyle(main=21, middle=3, sub=206))
    >>> abcf = knx_stack.GroupAddress(two_level_style=knx_stack.address.TwoLevelStyle(main=21, sub=975))

    >>> asap_1 = knx_stack.ASAP(1, "on/off light")
    >>> asap_2 = knx_stack.ASAP(2, "info on/off light")
    >>> asap_3 = knx_stack.ASAP(3, "two temperature sensors (together)")

    >>> address_table = knx_stack.AddressTable(individual_address, [], 255)
    >>> association_table = knx_stack.AssociationTable(address_table, [])
    >>> association_table.associate(asap_1, [abcd])
    >>> association_table.associate(asap_2, [abcd])
    >>> association_table.associate(asap_3, [abce, abcf])

    >>> group_object_table = knx_stack.GroupObjectTable({asap_1: knx_stack.datapointtypes.DPT_Switch,
    ...                                                  asap_2: knx_stack.datapointtypes.DPT_Switch,
    ...                                                  asap_3: knx_stack.datapointtypes.DPT_Value_Temp,
    ...                                                  })

    >>> association_table
    AssociationTable: asap -> addresses
        0 (individual address) -> [0x0001]
        1 (on/off light) -> [(0xABCD 21/973 21/3/205)]
        2 (info on/off light) -> [(0xABCD 21/973 21/3/205)]
        3 (two temperature sensors (together)) -> [(0xABCE 21/974 21/3/206), (0xABCF 21/975 21/3/207)]
    AddressTable: individual address: 0x0001, max_size=255
    <BLANKLINE>
        tsap -> individual address
        0 -> 0x0001
        tsap -> group address (hex_free_style two_level_style three_level_style)
        1 -> (0xABCD 21/973 21/3/205)
        2 -> (0xABCE 21/974 21/3/206)
        3 -> (0xABCF 21/975 21/3/207)
    <BLANKLINE>

    >>> group_object_table
    GroupObjectTable: ASAP -> datapointtype
        1 (on/off light) -> DPT_Switch
        2 (info on/off light) -> DPT_Switch
        3 (two temperature sensors (together)) -> DPT_Value_Temp
    <BLANKLINE>

USB HID decode/encode

    >>> state = knx_stack.State(knx_stack.state.Medium.usb_hid, association_table, group_object_table)

    >>> msg = knx_stack.Msg.make_from_str("0113130008000B010300002900BCE00001ABCD010080")
    >>> knx_stack.decode_msg(state, msg)
    [GroupValueWriteInd (DPT_Switch {'action': 'off'} for asap 1 (on/off light)), GroupValueWriteInd (DPT_Switch {'action': 'off'} for asap 2 (info on/off light))]
    >>> msg = knx_stack.Msg.make_from_str("0113130008000B010300002900BCE00001ABCC010081")
    >>> knx_stack.decode_msg(state, msg)
    []

    >>> msg = knx_stack.Msg.make_from_str("0113140008000C010300002900B4E00001ABCE02008005")
    >>> knx_stack.decode_msg(state, msg)
    [GroupValueWriteInd (DPT_Value_Temp: {'decoded_value': 0.05} for asap 3 (two temperature sensors (together)))]

    >>> req = knx_stack.layer.application.a_group_value_read.req.Msg(asap=asap_3)
    >>> knx_stack.encode_msg(state, req)
    0113130008000B01030000110096E00000ABCE010000

    >>> dpt = knx_stack.datapointtypes.DPT_Value_Temp()
    >>> dpt.encode(0.05)
    >>> req = knx_stack.layer.application.a_group_value_write.req.Msg(asap=asap_3, dpt=dpt)
    >>> knx_stack.encode_msg(state, req)
    0113150008000D01030000110096E00000ABCE0300800005

KNXnet IP decode/encode

    >>> state = knx_stack.knxnet_ip.State(knx_stack.state.Medium.knxnet_ip, association_table, group_object_table)

    >>> state.sequence_counter_remote = 1
    >>> msg = knx_stack.knxnet_ip.Msg.make_from_str("061004200015047401002900BCE00001ABCD010080")
    >>> knx_stack.decode_msg(state, msg)
    [TunnelingReq(sequence counter=1, status=<ErrorCodes.E_NO_ERROR: 0>), GroupValueWriteInd (DPT_Switch {'action': 'off'} for asap 1 (on/off light)), GroupValueWriteInd (DPT_Switch {'action': 'off'} for asap 2 (info on/off light))]
    >>> msg = knx_stack.knxnet_ip.Msg.make_from_str("061004200016047401002900B4E00001ABCE02008005")
    >>> knx_stack.decode_msg(state, msg)
    [TunnelingReq(sequence counter=1, status=<ErrorCodes.E_NO_ERROR: 0>), GroupValueWriteInd (DPT_Value_Temp: {'decoded_value': 0.05} for asap 3 (two temperature sensors (together)))]
    >>> req = knx_stack.layer.application.a_group_value_read.req.Msg(asap=asap_3)
    >>> knx_stack.encode_msg(state, req)
    06100420001504000000110096E00000ABCE010000

    >>> dpt = knx_stack.datapointtypes.DPT_Value_Temp()
    >>> dpt.encode(0.05)
    >>> req = knx_stack.layer.application.a_group_value_write.req.Msg(asap=asap_3, dpt=dpt)
    >>> knx_stack.encode_msg(state, req)
    06100420001704000000110096E00000ABCE0300800005

Encode from a dictionary

    >>> state = knx_stack.State(knx_stack.state.Medium.usb_hid, association_table, group_object_table)

    >>> factory = knx_stack.datapointtypes.DPT_Factory()
    >>> dpt = factory.make("DPT_Switch", {"action": "off"})
    >>> req = knx_stack.layer.application.a_group_value_write.req.Msg(asap=asap_1, dpt=dpt)
    >>> req
    GroupValueWriteReq (DPT_Switch {'action': 'off'} for asap 1 (on/off light))
    >>> knx_stack.encode_msg(state, req)
    0113130008000B01030000110096E00000ABCD010080

Decode to a dictionary

    >>> state = knx_stack.State(knx_stack.state.Medium.usb_hid, association_table, group_object_table)

    >>> msg = knx_stack.knxnet_ip.Msg.make_from_str("0113130008000B01030000290096E00000ABCD010080")
    >>> msgs = knx_stack.decode_msg(state, msg)
    >>> msgs
    [GroupValueWriteInd (DPT_Switch {'action': 'off'} for asap 1 (on/off light)), GroupValueWriteInd (DPT_Switch {'action': 'off'} for asap 2 (info on/off light))]
    >>> factory = knx_stack.datapointtypes.Description_Factory()
    >>> factory.make(msgs[0].dpt)
    ('DPT_Switch', {'action': 'off'})

Installation

pip install knx-stack

Diving In

Documentation

Contributing

Pull requests are welcome, and I am waiting for them.

License

knx-stack is licensed under the MIT license.

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

knx-stack-0.9.2.tar.gz (48.9 kB view details)

Uploaded Source

Built Distribution

knx_stack-0.9.2-py3-none-any.whl (126.2 kB view details)

Uploaded Python 3

File details

Details for the file knx-stack-0.9.2.tar.gz.

File metadata

  • Download URL: knx-stack-0.9.2.tar.gz
  • Upload date:
  • Size: 48.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.6.0 importlib_metadata/4.8.2 pkginfo/1.8.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.7

File hashes

Hashes for knx-stack-0.9.2.tar.gz
Algorithm Hash digest
SHA256 9062e69be2890c9ec12b951255109a4458231a02b148c506aee206f319208d50
MD5 bbab241b0336a86806316882b8cd7efa
BLAKE2b-256 8da5ec0e6692a415599a90c3c483f91ab118281061a3337122cabb01ead22f05

See more details on using hashes here.

File details

Details for the file knx_stack-0.9.2-py3-none-any.whl.

File metadata

  • Download URL: knx_stack-0.9.2-py3-none-any.whl
  • Upload date:
  • Size: 126.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.6.0 importlib_metadata/4.8.2 pkginfo/1.8.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.7

File hashes

Hashes for knx_stack-0.9.2-py3-none-any.whl
Algorithm Hash digest
SHA256 7460cb214586628d528e9af9a71d167e770cfc997c2ae57f931b59a7e9795e9c
MD5 3b143996ba6304b3d064944d968ebd48
BLAKE2b-256 f278ce98aa4b65ab94c0fecc859414ecd601896e9ef5fb466d951cfc5c88e6f1

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