{ "info": { "author": "Milan van Nugteren", "author_email": "milan@network23.nl", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", "Topic :: Software Development :: Libraries" ], "description": "# pyotgw\n\nA python library to interface with the OpenTherm Gateway\n\nSee http://otgw.tclcode.com for the hardware.\n\nThis library is written primarily for use with Home Assistant (https://www.home-assistant.io) but can be used for other purposes as well.\nParts of the code have not been thoroughly tested since my thermostat and boiler do not support all OpenTherm features. Feel free to test and contribute where you see fit.\n\n#### Contents\n- [Library Reference](#library-reference)\n - [General](#general)\n - [Getting Data](#getting-data)\n - [Methods](#methods)\n- [Usage Example](#usage-example)\n\n### Library Reference\n\n#### General\npyotgw exposes its pyotgw class which uses [pyserial-asyncio](https://pyserial-asyncio.readthedocs.io/en/latest/) to connect to the OpenTherm Gateway.\nAfter initialization of the object, `pyotgw.connect()` should be used to establish a connection. The object will maintain the connection in the background, using it to send commands and continuously receive updates. The received information will be cached on the object for instant availability.\nThe pyotgw object implements a watchdog to monitor the connection for inactivity. During `pyotgw.connect()`, an inactivity timeout can be set for this purpose. Normally, the OpenTherm Gateway will send a message on its serial interface approximately every second. If no messages are received for the duration of the timeout, the watchdog will trigger a reconnection attempt.\n\n#### Getting Data\nThere are multiple ways to get information from pyotgw. Calling `pyotgw.connect()` will request some initial information from the Gateway and return it in a dict. After this, the pyotgw object exposes quite a few methods which return values that are cached on the object. There is also the option to register a callback with `pyotgw.subscribe()` which will be called when any value changes.\n\n#### Methods\n\n---\n##### pyotgw()\nThe pyotgw constructor takes no arguments and returns an empty pyotgw object.\n\n---\n##### pyotgw.add_alternative(_self_, alt, timeout=OTGW_DEFAULT_TIMEOUT)\nAdd the specified data-ID to the list of alternative commands to send to the boiler instead of a data-ID that is known to be unsupported by the boiler.\nAlternative data-IDs will always be sent to the boiler in a Read-Data request message with the data-value set to zero. The table of alternative data-IDs is stored in non-volatile memory so it will persist even if the gateway has been powered off.\nThis method supports the following arguments:\n- __alt__ The alternative data-ID to add. Values from 1 to 255 are allowed.\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nReturns the ID that was added to the list, or None on failure.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.add_unknown_id(_self_, unknown_id, timeout=OTGW_DEFAULT_TIMEOUT)\nInform the gateway that the boiler doesn't support the specified data-ID, even if the boiler doesn't indicate that by returning an `unknown-dataID` response.\nUsing this command allows the gateway to send an alternative data-ID to the boiler instead.\nThis method supports the following arguments:\n- __unknown_id__ The data-ID to mark as unsupported. Values from 1 to 255 are allowed.\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nReturns the added ID, or None on failure.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.clear_response(_self_, data_id, timeout=OTGW_DEFAULT_TIMEOUT)\n__Not implemented yet.__\nClear response to the thermostat for a specific data_ID, which was previously configured with `pyotgw.set_response()`.\nThis method supports the following arguments:\n- __data_id__ The data-ID for which the response should be cleared. Values from 1 to 255 are allowed.\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nReturn the data ID for which the response was cleared, or None on failure.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.connect(_self_, loop, port, baudrate=9600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, connection_timeout=10, inactivity_timeout=5)\nConnect to an Opentherm Gateway and initializes the parameters obtained from the `PS` and `PR` commands.\nIf called while connected, reconnect to the gateway.\nAll optional serial-related arguments default to the OpenTherm Gateway default settings.\nThis method supports the following arguments:\n- __loop__ The event loop to use for the pyotgw object.\n- __port__ The port/url on which the OpenTherm Gateway can be reached as supported by [pyserial](https://pythonhosted.org/pyserial/url_handlers.html).\n- __baudrate__ The baud rate for the serial connection. Defaults to 9600.\n- __bytesize__ The byte size for the serial connection. Defaults to serial.EIGHTBITS.\n- __parity__ The parity for the serial connection. Defaults to serial.PARITY_NONE.\n- __stopbits__ The stop bits for the serial connection. Defaults to serial.STOPBITS_ONE.\n- __connection_timeout__ The timeout in seconds to use for the initial connection attempt. Defaults to 10.\n- __inactivity_timeout__ The inactivity timeout in seconds after which the watchdog will trigger a reconnect. A value of 3 or greater will enable the watchdog. Set to -1 to disable the watchdog. Defaults to 5.\n\nReturns a status dict with all known values.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.disconnect(_self_)\nDisconnect from the OpenTherm Gateway and clean up the object.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.del_alternative(_self_, alt, timeout=OTGW_DEFAULT_TIMEOUT)\nRemove the specified data-ID from the list of alternative commands.\nOnly one occurrence is deleted. If the data-ID appears multiple times in the list of alternative commands, this command must be repeated to delete all occurrences. The table of alternative data-IDs is stored in non-volatile memory so it will persist even if the gateway has been powered off. \nThis method supports the following arguments:\n- __alt__ The alternative data-ID to remove. Values from 1 to 255 are allowed.\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nReturns the ID that was removed from the list, or None on failure.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.del_unknown_id(_self_, unknown_id, timeout=OTGW_DEFAULT_TIMEOUT)\nStart forwarding the specified Data-ID to the boiler again.\nThis command resets the counter used to determine if the specified data-ID is supported by the boiler.\nThis method supports the following arguments:\n- __unknown_id__ The data-ID to mark as supported. Values from 1 to 255 are allowed.\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nReturn the ID that was marked as supported, or None on failure.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.get_gpio_mode(_self_, gpio_id)\nGet the mode for one of the GPIO pins.\nPossible modes are:\n- __0.__ No function, default for both ports on a freshly flashed chip.\n- __1.__ Ground - A permanently low output (0V). Could be used for a power LED.\n- __2.__ Vcc - A permanently high output (5V). Can be used as a short-proof power supply for some external circuitry used by the other GPIO port.\n- __3.__ LED E - An additional LED if you want to present more than 4 LED functions.\n- __4.__ LED F - An additional LED if you want to present more than 5 LED functions.\n- __5.__ Home - Set thermostat to setback temperature when pulled low.\n- __6.__ Away - Set thermostat to setback temperature when pulled high.\n- __7.__ DS1820 (GPIO port B only) - Data line for a DS18S20 or DS18B20 temperature sensor used to measure the outside temperature. A 4k7 resistor should be connected between GPIO port B and Vcc. \n\nThis method supports the following arguments:\n- __gpio_id__ The GPIO pin for which the mode is requested. Either `A` or `B`.\n\nReturns the mode for the requested GPIO pin.\n\n---\n##### pyotgw.get_hot_water_ovrd(_self_)\nGet the current hot water override setting.\n\nReturns the current hot water override mode if set, otherwise `None`.\n\n---\n##### pyotgw.get_led_mode(_self_, led_id)\nGet the mode for one of the LEDs.\nPossible modes are:\n- __R__ Receiving an Opentherm message from the thermostat or boiler\n- __X__ Transmitting an Opentherm message to the thermostat or boiler\n- __T__ Transmitting or receiving a message on the master interface\n- __B__ Transmitting or receiving a message on the slave interface\n- __O__ Remote setpoint override is active\n- __F__ Flame is on\n- __H__ Central heating is on\n- __W__ Hot water is on\n- __C__ Comfort mode (Domestic Hot Water Enable) is on\n- __E__ Transmission error has been detected\n- __M__ Boiler requires maintenance\n- __P__ Raised power mode active on thermostat interface. \n\nThis method supports the following arguments:\n- __led_id__ The LED for which the mode is requested. Must be a character in range `A-F`.\n\nReturns the mode for the requested LED.\n\n---\n##### pyotgw.get_mode(_self_)\nGet the current operating mode of the gateway.\n\nReturns `G` if the OpenTherm Gateway is operating in `gateway` mode or `M` for `monitor` mode.\n\n---\n##### pyotgw.get_outside_temp(_self_)\nGet the outside temperature as known in the gateway.\nThis method provides either the temperature from an external sensor connected to the OpenTherm system, or a value provided earlier with `pyotgw.set_outside_temp()`.\n\nReturns the outside air temperature as known in the OpenTherm Gateway.\n\n---\n##### pyotgw.get_reports(_self_)\nUpdate the pyotgw object with the information from all of the `PR` commands.\nThis method is also called from `pyotgw.connect()` to populate the status dict with initial values.\n\nReturns the full updated status dict.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.get_room_temp(_self_)\nGet the current room temperature.\nThis method provides the room temperature, normally measured by the thermostat.\n\nReturns the currently known room temperature.\n\n---\n##### pyotgw.get_setback_temp(_self_)\nGet the setback temperature.\nThe setback temperature is used in conjunction with `away mode` on the OpenTherm Gateway.\n\nReturns the currently known setback temperature.\n\n---\n##### pyotgw.get_status(_self_)\nUpdate the pyotgw object with the information from the `PS` command.\nThis method is also called from `pyotgw.connect()` to populate the status dict with initial values.\n\nReturns the full updated status dict.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.get_target_temp(_self_)\nGet the target temperature.\nThe target temperature is the temperature which the system is trying to reach. This can be the room setpoint remote override if set, or the current room setpoint.\n\nReturns the currently known target temperature.\n\n---\n##### pyotgw.prio_message(_self_, message, timeout=OTGW_DEFAULT_TIMEOUT)\n__Not implemented yet.__\nSend a priority message to the boiler.\nSpecify a one-time priority message to be sent to the boiler at the first opportunity. If the specified message returns the number of Transparent Slave Parameters (TSPs) or Fault History Buffers (FHBs), the gateway will proceed to request those TSPs or FHBs.\nThis method supports the following arguments:\n- __message__ The priority message to send.\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nThis method is a coroutine.\n\n---\n##### pyotgw.set_ch_enable_bit(_self_, ch_bit, timeout=OTGW_DEFAULT_TIMEOUT)\nSet or unset the `Central Heating Enable` bit.\nControl the CH enable status bit when overriding the control setpoint. By default the CH enable bit is set after a call to `pyotgw.set_control_setpoint ()` with a value other than 0. With this method, the bit can be manipulated.\nThis method supports the following arguments:\n- __ch_bit__ The new value for the `Central Heating Enable` bit. Can be either `0` or `1`.\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nReturn the newly accepted value (`0` or `1`), or `None` on failure.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.set_clock(_self_, date=datetime.now(), timeout=OTGW_DEFAULT_TIMEOUT)\nSet the clock on the thermostat.\nChange the time and day of the week of the thermostat. The gateway will send the specified time and day of the week in response to the next time and date message from the thermostat.\nThis method supports the following arguments:\n- __date__ A datetime object containing the time and day of the week to be sent to the thermostat. Defaults to `datetime.now()`.\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nReturns the accepted response from the gateway with format `HH:MM/DOW`, where DOW is a single digit: 1=Monday, 7=Sunday, or `None` on failure.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.set_control_setpoint(_self_, setpoint, timeout=OTGW_DEFAULT_TIMEOUT)\nSet the control setpoint.\nThe control setpoint is the target temperature for the water in the central heating system. This method will cause the OpenTherm Gateway to manipulate the control setpoint which is sent to the boiler. Set the control setpoint to `0` to pass along the value specified by the thermostat.\nThis method supports the following arguments:\n- __setpoint__ The new control setpoint.\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nReturns the newly accepted value, or `None` on failure.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.set_dhw_setpoint(_self_, temperature, timeout=OTGW_DEFAULT_TIMEOUT)\nSet the domestic hot water setpoint.\nThe domestic hot water setpoint is the target temperature for the hot water system. Not all boilers support this command.\nThis method supports the following arguments:\n- __temperature__ The new domestic hot water setpoint.\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nReturns the newly accepted setpoint, or `None` on failure.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.set_gpio_mode(_self_, gpio_id, mode, timeout=OTGW_DEFAULT_TIMEOUT)\nConfigure the functions of the two GPIO pins of the gateway.\nPossible modes are:\n- __0.__ No function, default for both ports on a freshly flashed chip.\n- __1.__ Ground - A permanently low output (0V). Could be used for a power LED.\n- __2.__ Vcc - A permanently high output (5V). Can be used as a short-proof power supply for some external circuitry used by the other GPIO port.\n- __3.__ LED E - An additional LED if you want to present more than 4 LED functions.\n- __4.__ LED F - An additional LED if you want to present more than 5 LED functions.\n- __5.__ Home - Set thermostat to setback temperature when pulled low.\n- __6.__ Away - Set thermostat to setback temperature when pulled high.\n- __7.__ DS1820 (GPIO port B only) - Data line for a DS18S20 or DS18B20 temperature sensor used to measure the outside temperature. A 4k7 resistor should be connected between GPIO port B and Vcc. \n\nThis method supports the following arguments:\n- __gpio_id__ The GPIO pin on which the mode is set. Either `A` or `B`.\n- __mode__ The requested mode for the GPIO pin. Values from `0` to `7` are supported (`7` only for GPIO `B`).\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nReturns the new mode for the specified gpio, or `None` on failure.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.set_hot_water_ovrd(_self_, state, timeout=OTGW_DEFAULT_TIMEOUT)\nControl the domestic hot water enable option.\nIf the boiler has been configured to let the room unit control when to keep a small amount of water preheated, this option can influence that. A state of `0` or `1` will override the domestic hot water option `off` or `on` respectively. Any other single character disables the override and resumes normal operation.\nThis method supports the following arguments:\n- __state__ The requested state for the domestic hot water option.\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nReturns the accepted value, `A` if the override is disabled or `None` on failure.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.set_led_mode(_self_, led_id, mode, timeout=OTGW_DEFAULT_TIMEOUT)\nSet the mode of one of the LEDs.\nConfigure the functions of the six LEDs (A-F) that can optionally be connected to pins RB3/RB4/RB6/RB7 and the GPIO pins of the PIC.\nPossible modes are:\n- __R__ Receiving an Opentherm message from the thermostat or boiler\n- __X__ Transmitting an Opentherm message to the thermostat or boiler\n- __T__ Transmitting or receiving a message on the master interface\n- __B__ Transmitting or receiving a message on the slave interface\n- __O__ Remote setpoint override is active\n- __F__ Flame is on\n- __H__ Central heating is on\n- __W__ Hot water is on\n- __C__ Comfort mode (Domestic Hot Water Enable) is on\n- __E__ Transmission error has been detected\n- __M__ Boiler requires maintenance\n- __P__ Raised power mode active on thermostat interface. \n\nThis method supports the following arguments:\n- __led_id__ The LED for which the mode is set. Must be a character in the range `A-F`.\n- __mode__ The requested state for the LED. Must be one of `R`, `X`, `T`, `B`, `O`, `F`, `H`, `W`, `C`, `E`, `M` or `P`.\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nReturns the new mode for the specified LED, or `None` on failure.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.set_max_ch_setpoint(_self_, temperature, timeout=OTGW_DEFAULT_TIMEOUT)\nSet the maximum central heating water setpoint.\nNot all boilers support this option.\n\nThis method supports the following arguments:\n- __temperature__ The new maximum central heating water setpoint.\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nReturns the newly accepted setpoint, or `None` on failure.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.set_max_relative_mod(_self_, max_mod, timeout=OTGW_DEFAULT_TIMEOUT)\nSet the maximum relative modulation level.\nOverride the maximum relative modulation from the thermostat. Valid values are 0 through 100. Clear the setting by specifying a non-numeric value.\nThis method supports the following arguments:\n- __temperature__ The new maximum central heating water setpoint.\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nReturns the newly accepted value, `-` if a previous value was cleared, or `None` on failure.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.set_mode(_self_, mode, timeout=OTGW_DEFAULT_TIMEOUT)\nSet the operating mode of the gateway.\nThe operating mode can be either `gateway` or `monitor` mode. This method can also be used to reset the OpenTherm Gateway.\nThis method supports the following arguments:\n- __mode__ The mode to be set on the gateway. Can be `0` or `OTGW_MODE_MONITOR` for `monitor` mode, `1` or `OTGW_MODE_GATEWAY` for `gateway mode, or `OTGW_MODE_RESET` to reset the gateway.\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nReturn the newly activated mode, or the full renewed status dict after a reset.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.set_outside_temp(_self_, temp, timeout=OTGW_DEFAULT_TIMEOUT)\nSet the outside temperature.\nConfigure the outside temperature to send to the thermostat. Allowed values are between -40.0 and +64.0, although thermostats may not display the full range. Specify a value above 64 (suggestion: 99) to clear a previously configured value.\nThis method supports the following arguments:\n- __temp__ The outside temperature to provide to the gateway.\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nReturns the accepted value on success, `-` if a previously configured value has been cleared or `None` on failure.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.set_response(_self_, data_id, data, timeout=OTGW_DEFAULT_TIMEOUT)\n__Not implemented yet.__\nConfigure a response to send back to the thermostat instead of the response produced by the boiler.\nThis method supports the following arguments:\n- __data_id__ The data-ID for which the response should be set. Values from 1 to 255 are allowed.\n- __data__ A list of one or two hex byte values to be passed along with the data_id.\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nReturns the data ID for which the response was set, or `None` on\nfailure.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.set_setback_temp(_self_, sb_temp, timeout=OTGW_DEFAULT_TIMEOUT)\nSet the setback temperature.\nConfigure the setback temperature to use in combination with the GPIO functions `home`(5) and `away`(6).\nThis method supports the following arguments:\n- __sb_temp__ The new setback temperature.\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nReturns the new setback temperature, or `None` on failure.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.set_target_temp(_self_, temp, temporary=True, timeout=OTGW_DEFAULT_TIMEOUT)\nSet the room setpoint.\nConfigure the thermostat setpoint and specify whether or not it may be overridden by a programmed change.\nThis method supports the following arguments:\n- __temp__ The new room setpoint. Will be formatted to 1 decimal.\n- __temporary__ Whether or not the thermostat program may override the room setpoint. Either `True` or `False`. Defaults to `True`.\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nReturns the newly accepted room setpoint, or `None` on failure.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.set_ventilation(_self_, pct, timeout=OTGW_DEFAULT_TIMEOUT)\nSet the ventilation setpoint.\nConfigure a ventilation setpoint override value (0-100%).\nThis method supports the following arguments:\n- __pct__ The new ventilation setpoint. Must be between `0` and `100`.\n- __timeout__ The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).\n\nReturn the newly accepted value, or `None` on failure.\n\nThis method is a coroutine.\n\n---\n##### pyotgw.subscribe(_self_, coro)\nSubscribe to status updates from the Opentherm Gateway.\nCan only be used after `pyotgw.connect()`.\nThe subscribed coroutine must have the following signature:\n```\nasync def coro(status)\n```\nWhere `status` will be the full status dict containing the last known information from the OpenTherm Gateway.\nThis method supports the following arguments:\n- __coro__ A coroutine which will be called whenever a status change occurs.\n\nReturns `True` on success, `False` if not connected or if the coroutine is already subscribed.\n\n---\n##### pyotgw.unsubscribe(_self_, coro)\nUnsubscribe from status updates from the Opentherm Gateway.\nCan only be used after `pyotgw.connect()`. The supplied coroutine must have been subscribed with `pyotgw.subscribe()` before.\nThis method supports the following arguments:\n- __coro__ The coroutine which will be unsubscribed.\n\nReturns `True` on success, `False` if not connected or if the coroutine was not subscribed before.\n\n---\n\n\n### Usage Example\n```python\nimport asyncio\nfrom pyotgw import pyotgw\n\nPORT = '/dev/ttyUSB0'\n\n\nasync def print_status(status):\n \"\"\"Receive and print status.\"\"\"\n print(\"Received a status update:\\n{}\".format(status))\n\n\nasync def connect_and_subscribe():\n \"\"\"Connect to the OpenTherm Gateway and subscribe to status updates.\"\"\"\n\n # Create the object\n gw = pyotgw()\n\n # Connect to OpenTherm Gateway on PORT\n status = await gw.connect(asyncio.get_event_loop(), PORT)\n print(\"Initial status after connecting:\\n{}\".format(status))\n\n # Subscribe to updates from the gateway\n if not gw.subscribe(print_status):\n print(\"Could not subscribe to status updates.\")\n\n # Keep the event loop alive...\n while True:\n await asyncio.sleep(1)\n\n\n# Set up the event loop and run the connect_and_subscribe coroutine.\nloop = asyncio.get_event_loop()\ntry:\n loop.run_until_complete(connect_and_subscribe())\nexcept KeyboardInterrupt:\n print(\"Exiting\")\n\n```\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/mvn23/pyotgw", "keywords": "opentherm gateway otgw", "license": "GPLv3+", "maintainer": "", "maintainer_email": "", "name": "pyotgw", "package_url": "https://pypi.org/project/pyotgw/", "platform": "", "project_url": "https://pypi.org/project/pyotgw/", "project_urls": { "Homepage": "https://github.com/mvn23/pyotgw" }, "release_url": "https://pypi.org/project/pyotgw/0.5b0/", "requires_dist": [ "pyserial-asyncio" ], "requires_python": "", "summary": "A library to interface with the opentherm gateway through serial or network connection.", "version": "0.5b0" }, "last_serial": 5917568, "releases": { "0.1a0": [ { "comment_text": "", "digests": { "md5": "1db462ce7ce6b58be68a79cc64a9509a", "sha256": "2110a08e29e92b616515f2bf81b5472841a090d19e94db17a1e32e668e1d48d0" }, "downloads": -1, "filename": "pyotgw-0.1a0-py3-none-any.whl", "has_sig": false, "md5_digest": "1db462ce7ce6b58be68a79cc64a9509a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 16167, "upload_time": "2018-08-28T23:09:24", "url": "https://files.pythonhosted.org/packages/96/e1/f4533309065c819e76a89b59a9dd6e21b8d4622f37b29c77663787073ee9/pyotgw-0.1a0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "7f83789d752bb4fb7b1e1aed10ce8175", "sha256": "2c492f37c31fd4ad22e45530c0cf723bc69538820df3946daa8ced1ba1b445ba" }, "downloads": -1, "filename": "pyotgw-0.1a0.tar.gz", "has_sig": false, "md5_digest": "7f83789d752bb4fb7b1e1aed10ce8175", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14682, "upload_time": "2018-08-28T23:09:26", "url": "https://files.pythonhosted.org/packages/e0/cb/c930da208b3f33bd8c788b8328af8319cd1037071b5fcce92053a1f76006/pyotgw-0.1a0.tar.gz" } ], "0.1b0": [ { "comment_text": "", "digests": { "md5": "80823cee9bd2adb4876752320225195b", "sha256": "9007a5b91a3126d45b0cfc2d1eaa9861016453ffa01faf8d8731e7d2a2dd23ba" }, "downloads": -1, "filename": "pyotgw-0.1b0-py3-none-any.whl", "has_sig": false, "md5_digest": "80823cee9bd2adb4876752320225195b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 16183, "upload_time": "2018-09-05T12:46:07", "url": "https://files.pythonhosted.org/packages/ad/bc/356d1b64e4b112314517a4612de0f5fc7384de08cab0eec53a5e2bf508ca/pyotgw-0.1b0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "56a0283a50f447dd1d82629ea2cf316e", "sha256": "488cb2bb3d0f2a3adb30056ad499533916f6b45a2e7ea647ba08185e6602d31d" }, "downloads": -1, "filename": "pyotgw-0.1b0.tar.gz", "has_sig": false, "md5_digest": "56a0283a50f447dd1d82629ea2cf316e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14693, "upload_time": "2018-09-05T12:46:09", "url": "https://files.pythonhosted.org/packages/2e/be/64c1e29b855a50247e57c435aa0b34adbe64fa9c24415491eef1f0ad84aa/pyotgw-0.1b0.tar.gz" } ], "0.2b1": [ { "comment_text": "", "digests": { "md5": "032a42a68e8aa55f1fd0ca7054097e3e", "sha256": "2533d4c3c3da7707b4df1e89753b2dfc907ddb9b1d3a7533741f73689bab9846" }, "downloads": -1, "filename": "pyotgw-0.2b1-py3-none-any.whl", "has_sig": false, "md5_digest": "032a42a68e8aa55f1fd0ca7054097e3e", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 28048, "upload_time": "2018-10-12T11:46:10", "url": "https://files.pythonhosted.org/packages/45/a1/28eb21e8e4d939491953763d98ba502b25fdfb80ad4363fd0694179b107a/pyotgw-0.2b1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "6bd251ec6e0758e66afb3b61ccaf7231", "sha256": "83e8c743fcafdfb74061691d5b365cc8912878e097dafa0dd7ee542094309efb" }, "downloads": -1, "filename": "pyotgw-0.2b1.tar.gz", "has_sig": false, "md5_digest": "6bd251ec6e0758e66afb3b61ccaf7231", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14270, "upload_time": "2018-10-12T11:46:12", "url": "https://files.pythonhosted.org/packages/0a/3d/a8c367c10eb1dd1fb6e5809e465ad7b9ef2640de41416798312f42582722/pyotgw-0.2b1.tar.gz" } ], "0.3b0": [ { "comment_text": "", "digests": { "md5": "a850468dee460d01785122d718ba8dab", "sha256": "d0f6bcaec16dd505d8997e85ea2929b1b74eea10ecaee8826dbbca8a6870e682" }, "downloads": -1, "filename": "pyotgw-0.3b0-py3-none-any.whl", "has_sig": false, "md5_digest": "a850468dee460d01785122d718ba8dab", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 29116, "upload_time": "2018-10-24T11:14:46", "url": "https://files.pythonhosted.org/packages/6d/5f/4a2a2004c2c6ce18104e7b9a08e3c3088e265f083dc16ea396c121c9a5d7/pyotgw-0.3b0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "18e5d9f82f2c1298b4d4b0c556122f84", "sha256": "4730233646c8e5f4f627d5334455bfbaf2d7a3ba3abeff2e2f41a5686b182c37" }, "downloads": -1, "filename": "pyotgw-0.3b0.tar.gz", "has_sig": false, "md5_digest": "18e5d9f82f2c1298b4d4b0c556122f84", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15208, "upload_time": "2018-10-24T11:14:48", "url": "https://files.pythonhosted.org/packages/49/9a/4a73b5f5cbde13135f26721cf59ff1c8e1b28e3a80be6d203b64ed7740e9/pyotgw-0.3b0.tar.gz" } ], "0.3b1": [ { "comment_text": "", "digests": { "md5": "ab0cf969992d8d79636a26864b9a7497", "sha256": "b2a38577bf619eb33b8371ca48e3aa9edf7b9d75f06f9de112a2ee3f26f567bc" }, "downloads": -1, "filename": "pyotgw-0.3b1-py3-none-any.whl", "has_sig": false, "md5_digest": "ab0cf969992d8d79636a26864b9a7497", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 29172, "upload_time": "2018-11-07T00:40:46", "url": "https://files.pythonhosted.org/packages/d0/52/e24ece1bfc4babe7b2c51c5da73721f0dd71be888ad929ace1c164ca5f1e/pyotgw-0.3b1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "3a2244e3220b01d2265c5fe01408a385", "sha256": "527aa91c6b28a2cfa9d68b682ec9728616ad9ba7e2c1796758ffead22e987958" }, "downloads": -1, "filename": "pyotgw-0.3b1.tar.gz", "has_sig": false, "md5_digest": "3a2244e3220b01d2265c5fe01408a385", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15260, "upload_time": "2018-11-07T00:40:49", "url": "https://files.pythonhosted.org/packages/6d/2e/dbe345917d36c7418cf503e6d0133ec493cc37d8668bba9ccda66be0548b/pyotgw-0.3b1.tar.gz" } ], "0.4b0": [ { "comment_text": "", "digests": { "md5": "22169aea5b783e21ba1e5c16b716ca94", "sha256": "585d050ae3ece4c53149348fd59e6ffad0da37d2e2ccc2a09e0ab2bf70fd81d4" }, "downloads": -1, "filename": "pyotgw-0.4b0-py3-none-any.whl", "has_sig": false, "md5_digest": "22169aea5b783e21ba1e5c16b716ca94", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 30536, "upload_time": "2018-12-28T13:48:33", "url": "https://files.pythonhosted.org/packages/10/01/47b4f7ace037d7e70ad04616f0762e1fd129c46f311617ecdb9c6f159942/pyotgw-0.4b0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "02dab800ac57f7eb0ea69b8273acef5b", "sha256": "d6aee29e75cc656093f0b1b464375e43e20f420434d6a261e437b7331e04da81" }, "downloads": -1, "filename": "pyotgw-0.4b0.tar.gz", "has_sig": false, "md5_digest": "02dab800ac57f7eb0ea69b8273acef5b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16582, "upload_time": "2018-12-28T13:48:38", "url": "https://files.pythonhosted.org/packages/fd/1a/2c33c5d443936eef28193190ec79764b150c809cbaed373f4e5e4691562f/pyotgw-0.4b0.tar.gz" } ], "0.4b1": [ { "comment_text": "", "digests": { "md5": "96b56d595fd5fcc0992352a8ab47f3db", "sha256": "97d3d3ef9cc33ed4bc378b893864c7e5645374d080c360989a2f819e3ca94f8f" }, "downloads": -1, "filename": "pyotgw-0.4b1-py3-none-any.whl", "has_sig": false, "md5_digest": "96b56d595fd5fcc0992352a8ab47f3db", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 30644, "upload_time": "2019-01-02T10:53:38", "url": "https://files.pythonhosted.org/packages/4c/90/d6cf1b8e33bb7c16262acb90a4f2088c20b2e355f68e6ec804760c9661a6/pyotgw-0.4b1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "74914e0b2d7757b97537eaebf591993c", "sha256": "46a26e4ba4563fd86886b1acf93825c15e6e82394c273ef607d4a4e910bad775" }, "downloads": -1, "filename": "pyotgw-0.4b1.tar.gz", "has_sig": false, "md5_digest": "74914e0b2d7757b97537eaebf591993c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16684, "upload_time": "2019-01-02T10:53:44", "url": "https://files.pythonhosted.org/packages/ad/6c/29bb5dc5b0b7b4d71e401b0e6f443e92209add555439f0002a8e9f624e96/pyotgw-0.4b1.tar.gz" } ], "0.4b2": [ { "comment_text": "", "digests": { "md5": "c331f3b796bf682bfa1b2539c71c6c94", "sha256": "8809a75602def9b7a71c5467524c6375bd9f1fd391bc266598bb39a15fbe8828" }, "downloads": -1, "filename": "pyotgw-0.4b2-py3-none-any.whl", "has_sig": false, "md5_digest": "c331f3b796bf682bfa1b2539c71c6c94", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 36087, "upload_time": "2019-03-12T16:41:43", "url": "https://files.pythonhosted.org/packages/6d/f4/3f7d324b5fe3a35f1eb012376e525677d55a98d01f1a5665fadb66bf2711/pyotgw-0.4b2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2c544c2caffabddbbaabd35f8eb769c5", "sha256": "0d23731e7d9c09fc3bdb9060bf6c68287aa30b622f97f7d219504db9d6217817" }, "downloads": -1, "filename": "pyotgw-0.4b2.tar.gz", "has_sig": false, "md5_digest": "2c544c2caffabddbbaabd35f8eb769c5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27876, "upload_time": "2019-03-12T16:41:48", "url": "https://files.pythonhosted.org/packages/2e/da/9c1b48ab694e1f029ad7580ca071bcbbfa419c8e0be8e36e191d3d599bb7/pyotgw-0.4b2.tar.gz" } ], "0.4b3": [ { "comment_text": "", "digests": { "md5": "1e1f18f51505c9e529af416b4273968f", "sha256": "ad825fd856617c07bc9ed064c837a0c00d6e1c38cf5232fc648cbb01665f038c" }, "downloads": -1, "filename": "pyotgw-0.4b3-py3-none-any.whl", "has_sig": false, "md5_digest": "1e1f18f51505c9e529af416b4273968f", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 36480, "upload_time": "2019-03-28T10:17:32", "url": "https://files.pythonhosted.org/packages/1f/76/f6d9a7024b3d2ea71c015ded8a4bb832a2fc84e71bbaab2e4b9e21ba1c0a/pyotgw-0.4b3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ca5e6a2d99f31b82148104c367641684", "sha256": "ad6971f2f5a7ec830061e284203a5486fd9289a784816cf473c00e612ab7d9a0" }, "downloads": -1, "filename": "pyotgw-0.4b3.tar.gz", "has_sig": false, "md5_digest": "ca5e6a2d99f31b82148104c367641684", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 28296, "upload_time": "2019-03-28T10:17:34", "url": "https://files.pythonhosted.org/packages/7a/ea/5b6e416d87d7e2fd29f531177642f02900e4b962c9c00f85505024ba6531/pyotgw-0.4b3.tar.gz" } ], "0.4b4": [ { "comment_text": "", "digests": { "md5": "73f1fd79a73ce0990dd7d2ba39367bb9", "sha256": "5c31d03e5ece1cfd3703f96f18d08a934400222bb99da611febf1e367a6bc011" }, "downloads": -1, "filename": "pyotgw-0.4b4-py3-none-any.whl", "has_sig": false, "md5_digest": "73f1fd79a73ce0990dd7d2ba39367bb9", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 36517, "upload_time": "2019-05-11T08:29:20", "url": "https://files.pythonhosted.org/packages/23/2d/d641ddf154fa5bbd0a1d0a1b750bf1fa04e72148ae75ec9a5c49b3569519/pyotgw-0.4b4-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "554f487ff0074dc169e52644012e668f", "sha256": "72260ace84571772c5cadb9cad7a8fc2a60e516738d33f076abde0d5e39be32e" }, "downloads": -1, "filename": "pyotgw-0.4b4.tar.gz", "has_sig": false, "md5_digest": "554f487ff0074dc169e52644012e668f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 28333, "upload_time": "2019-05-11T08:29:22", "url": "https://files.pythonhosted.org/packages/b9/1e/0dd43f8712728c3b295a4a4cae089c7bd2e877fea85ed0ecaaf26a68926d/pyotgw-0.4b4.tar.gz" } ], "0.5b0": [ { "comment_text": "", "digests": { "md5": "5af6387227cbca14225c1f7f7371996a", "sha256": "31e8c191007d99c454780a008845be631a24ce3324de420f8b0b50714e0f0e95" }, "downloads": -1, "filename": "pyotgw-0.5b0-py3-none-any.whl", "has_sig": false, "md5_digest": "5af6387227cbca14225c1f7f7371996a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 36654, "upload_time": "2019-10-02T12:06:48", "url": "https://files.pythonhosted.org/packages/96/27/634c3a51e5d6a6cf5b0b021377386d9c5fe90dc02658f3fb6e41f256f09e/pyotgw-0.5b0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "fbf614a49e671b099ec467893899bd50", "sha256": "5ad0263f68a68cdd52581c579c2d7a4522b7aaaf0897d86edb14d7343f073839" }, "downloads": -1, "filename": "pyotgw-0.5b0.tar.gz", "has_sig": false, "md5_digest": "fbf614a49e671b099ec467893899bd50", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 28492, "upload_time": "2019-10-02T12:06:51", "url": "https://files.pythonhosted.org/packages/02/67/60e7558b3eba7dcc405e444189dcf97da6943fdc174f7f686cbeeed55599/pyotgw-0.5b0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "5af6387227cbca14225c1f7f7371996a", "sha256": "31e8c191007d99c454780a008845be631a24ce3324de420f8b0b50714e0f0e95" }, "downloads": -1, "filename": "pyotgw-0.5b0-py3-none-any.whl", "has_sig": false, "md5_digest": "5af6387227cbca14225c1f7f7371996a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 36654, "upload_time": "2019-10-02T12:06:48", "url": "https://files.pythonhosted.org/packages/96/27/634c3a51e5d6a6cf5b0b021377386d9c5fe90dc02658f3fb6e41f256f09e/pyotgw-0.5b0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "fbf614a49e671b099ec467893899bd50", "sha256": "5ad0263f68a68cdd52581c579c2d7a4522b7aaaf0897d86edb14d7343f073839" }, "downloads": -1, "filename": "pyotgw-0.5b0.tar.gz", "has_sig": false, "md5_digest": "fbf614a49e671b099ec467893899bd50", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 28492, "upload_time": "2019-10-02T12:06:51", "url": "https://files.pythonhosted.org/packages/02/67/60e7558b3eba7dcc405e444189dcf97da6943fdc174f7f686cbeeed55599/pyotgw-0.5b0.tar.gz" } ] }