Skip to content
/ pyotgw Public
forked from mvn23/pyotgw

A library to interface with the OpenTherm Gateway through serial or network connection.

License

Notifications You must be signed in to change notification settings

andriej/pyotgw

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

47 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pyotgw

A python library to interface with the OpenTherm Gateway

See http://otgw.tclcode.com for the hardware.

This library is written primarily for use with Home Assistant (https://www.home-assistant.io) but can be used for other purposes as well. Parts 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.

Contents

Library Reference

General

pyotgw exposes its pyotgw class which uses pyserial-asyncio to connect to the OpenTherm Gateway. After 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. The 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.

Getting Data

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

Methods


pyotgw()

The pyotgw constructor takes no arguments and returns an empty pyotgw object.


pyotgw.add_alternative(self, alt, timeout=OTGW_DEFAULT_TIMEOUT)

Add 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. Alternative 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. This method supports the following arguments:

  • alt The alternative data-ID to add. Values from 1 to 255 are allowed.
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

Returns the ID that was added to the list, or None on failure.

This method is a coroutine.


pyotgw.add_unknown_id(self, unknown_id, timeout=OTGW_DEFAULT_TIMEOUT)

Inform 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. Using this command allows the gateway to send an alternative data-ID to the boiler instead. This method supports the following arguments:

  • unknown_id The data-ID to mark as unsupported. Values from 1 to 255 are allowed.
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

Returns the added ID, or None on failure.

This method is a coroutine.


pyotgw.clear_response(self, data_id, timeout=OTGW_DEFAULT_TIMEOUT)

Not implemented yet. Clear response to the thermostat for a specific data_ID, which was previously configured with pyotgw.set_response(). This method supports the following arguments:

  • data_id The data-ID for which the response should be cleared. Values from 1 to 255 are allowed.
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

Return the data ID for which the response was cleared, or None on failure.

This method is a coroutine.


pyotgw.connect(self, loop, port, baudrate=9600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, connection_timeout=10, inactivity_timeout=5)

Connect to an Opentherm Gateway and initializes the parameters obtained from the PS and PR commands. If called while connected, reconnect to the gateway. All optional serial-related arguments default to the OpenTherm Gateway default settings. This method supports the following arguments:

  • loop The event loop to use for the pyotgw object.
  • port The port/url on which the OpenTherm Gateway can be reached as supported by pyserial.
  • baudrate The baud rate for the serial connection. Defaults to 9600.
  • bytesize The byte size for the serial connection. Defaults to serial.EIGHTBITS.
  • parity The parity for the serial connection. Defaults to serial.PARITY_NONE.
  • stopbits The stop bits for the serial connection. Defaults to serial.STOPBITS_ONE.
  • connection_timeout The timeout in seconds to use for the initial connection attempt. Defaults to 10.
  • 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.

Returns a status dict with all known values.

This method is a coroutine.


pyotgw.disconnect(self)

Disconnect from the OpenTherm Gateway and clean up the object.

This method is a coroutine.


pyotgw.del_alternative(self, alt, timeout=OTGW_DEFAULT_TIMEOUT)

Remove the specified data-ID from the list of alternative commands. Only 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. This method supports the following arguments:

  • alt The alternative data-ID to remove. Values from 1 to 255 are allowed.
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

Returns the ID that was removed from the list, or None on failure.

This method is a coroutine.


pyotgw.del_unknown_id(self, unknown_id, timeout=OTGW_DEFAULT_TIMEOUT)

Start forwarding the specified Data-ID to the boiler again. This command resets the counter used to determine if the specified data-ID is supported by the boiler. This method supports the following arguments:

  • unknown_id The data-ID to mark as supported. Values from 1 to 255 are allowed.
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

Return the ID that was marked as supported, or None on failure.

This method is a coroutine.


pyotgw.get_gpio_mode(self, gpio_id)

Get the mode for one of the GPIO pins. Possible modes are:

  • 0. No function, default for both ports on a freshly flashed chip.
  • 1. Ground - A permanently low output (0V). Could be used for a power LED.
  • 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.
  • 3. LED E - An additional LED if you want to present more than 4 LED functions.
  • 4. LED F - An additional LED if you want to present more than 5 LED functions.
  • 5. Home - Set thermostat to setback temperature when pulled low.
  • 6. Away - Set thermostat to setback temperature when pulled high.
  • 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.

This method supports the following arguments:

  • gpio_id The GPIO pin for which the mode is requested. Either A or B.

Returns the mode for the requested GPIO pin.


pyotgw.get_hot_water_ovrd(self)

Get the current hot water override setting.

Returns the current hot water override mode if set, otherwise None.


pyotgw.get_led_mode(self, led_id)

Get the mode for one of the LEDs. Possible modes are:

  • R Receiving an Opentherm message from the thermostat or boiler
  • X Transmitting an Opentherm message to the thermostat or boiler
  • T Transmitting or receiving a message on the master interface
  • B Transmitting or receiving a message on the slave interface
  • O Remote setpoint override is active
  • F Flame is on
  • H Central heating is on
  • W Hot water is on
  • C Comfort mode (Domestic Hot Water Enable) is on
  • E Transmission error has been detected
  • M Boiler requires maintenance
  • P Raised power mode active on thermostat interface.

This method supports the following arguments:

  • led_id The LED for which the mode is requested. Must be a character in range A-F.

Returns the mode for the requested LED.


pyotgw.get_mode(self)

Get the current operating mode of the gateway.

Returns G if the OpenTherm Gateway is operating in gateway mode or M for monitor mode.


pyotgw.get_outside_temp(self)

Get the outside temperature as known in the gateway. This method provides either the temperature from an external sensor connected to the OpenTherm system, or a value provided earlier with pyotgw.set_outside_temp().

Returns the outside air temperature as known in the OpenTherm Gateway.


pyotgw.get_reports(self)

Update the pyotgw object with the information from all of the PR commands. This method is also called from pyotgw.connect() to populate the status dict with initial values.

Returns the full updated status dict.

This method is a coroutine.


pyotgw.get_room_temp(self)

Get the current room temperature. This method provides the room temperature, normally measured by the thermostat.

Returns the currently known room temperature.


pyotgw.get_setback_temp(self)

Get the setback temperature. The setback temperature is used in conjunction with away mode on the OpenTherm Gateway.

Returns the currently known setback temperature.


pyotgw.get_status(self)

Update the pyotgw object with the information from the PS command. This method is also called from pyotgw.connect() to populate the status dict with initial values.

Returns the full updated status dict.

This method is a coroutine.


pyotgw.get_target_temp(self)

Get the target temperature. The 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.

Returns the currently known target temperature.


pyotgw.prio_message(self, message, timeout=OTGW_DEFAULT_TIMEOUT)

Not implemented yet. Send a priority message to the boiler. Specify 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. This method supports the following arguments:

  • message The priority message to send.
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

This method is a coroutine.


pyotgw.set_ch_enable_bit(self, ch_bit, timeout=OTGW_DEFAULT_TIMEOUT)

Set or unset the Central Heating Enable bit. Control 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. This method supports the following arguments:

  • ch_bit The new value for the Central Heating Enable bit. Can be either 0 or 1.
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

Return the newly accepted value (0 or 1), or None on failure.

This method is a coroutine.


pyotgw.set_clock(self, date=datetime.now(), timeout=OTGW_DEFAULT_TIMEOUT)

Set the clock on the thermostat. Change 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. This method supports the following arguments:

  • date A datetime object containing the time and day of the week to be sent to the thermostat. Defaults to datetime.now().
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

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

This method is a coroutine.


pyotgw.set_control_setpoint(self, setpoint, timeout=OTGW_DEFAULT_TIMEOUT)

Set the control setpoint. The 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. This method supports the following arguments:

  • setpoint The new control setpoint.
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

Returns the newly accepted value, or None on failure.

This method is a coroutine.


pyotgw.set_dhw_setpoint(self, temperature, timeout=OTGW_DEFAULT_TIMEOUT)

Set the domestic hot water setpoint. The domestic hot water setpoint is the target temperature for the hot water system. Not all boilers support this command. This method supports the following arguments:

  • temperature The new domestic hot water setpoint.
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

Returns the newly accepted setpoint, or None on failure.

This method is a coroutine.


pyotgw.set_gpio_mode(self, gpio_id, mode, timeout=OTGW_DEFAULT_TIMEOUT)

Configure the functions of the two GPIO pins of the gateway. Possible modes are:

  • 0. No function, default for both ports on a freshly flashed chip.
  • 1. Ground - A permanently low output (0V). Could be used for a power LED.
  • 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.
  • 3. LED E - An additional LED if you want to present more than 4 LED functions.
  • 4. LED F - An additional LED if you want to present more than 5 LED functions.
  • 5. Home - Set thermostat to setback temperature when pulled low.
  • 6. Away - Set thermostat to setback temperature when pulled high.
  • 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.

This method supports the following arguments:

  • gpio_id The GPIO pin on which the mode is set. Either A or B.
  • mode The requested mode for the GPIO pin. Values from 0 to 7 are supported (7 only for GPIO B).
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

Returns the new mode for the specified gpio, or None on failure.

This method is a coroutine.


pyotgw.set_hot_water_ovrd(self, state, timeout=OTGW_DEFAULT_TIMEOUT)

Control the domestic hot water enable option. If 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. This method supports the following arguments:

  • state The requested state for the domestic hot water option.
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

Returns the accepted value, A if the override is disabled or None on failure.

This method is a coroutine.


pyotgw.set_led_mode(self, led_id, mode, timeout=OTGW_DEFAULT_TIMEOUT)

Set the mode of one of the LEDs. Configure 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. Possible modes are:

  • R Receiving an Opentherm message from the thermostat or boiler
  • X Transmitting an Opentherm message to the thermostat or boiler
  • T Transmitting or receiving a message on the master interface
  • B Transmitting or receiving a message on the slave interface
  • O Remote setpoint override is active
  • F Flame is on
  • H Central heating is on
  • W Hot water is on
  • C Comfort mode (Domestic Hot Water Enable) is on
  • E Transmission error has been detected
  • M Boiler requires maintenance
  • P Raised power mode active on thermostat interface.

This method supports the following arguments:

  • led_id The LED for which the mode is set. Must be a character in the range A-F.
  • mode The requested state for the LED. Must be one of R, X, T, B, O, F, H, W, C, E, M or P.
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

Returns the new mode for the specified LED, or None on failure.

This method is a coroutine.


pyotgw.set_max_ch_setpoint(self, temperature, timeout=OTGW_DEFAULT_TIMEOUT)

Set the maximum central heating water setpoint. Not all boilers support this option.

This method supports the following arguments:

  • temperature The new maximum central heating water setpoint.
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

Returns the newly accepted setpoint, or None on failure.

This method is a coroutine.


pyotgw.set_max_relative_mod(self, max_mod, timeout=OTGW_DEFAULT_TIMEOUT)

Set the maximum relative modulation level. Override the maximum relative modulation from the thermostat. Valid values are 0 through 100. Clear the setting by specifying a non-numeric value. This method supports the following arguments:

  • temperature The new maximum central heating water setpoint.
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

Returns the newly accepted value, - if a previous value was cleared, or None on failure.

This method is a coroutine.


pyotgw.set_mode(self, mode, timeout=OTGW_DEFAULT_TIMEOUT)

Set the operating mode of the gateway. The operating mode can be either gateway or monitor mode. This method can also be used to reset the OpenTherm Gateway. This method supports the following arguments:

  • 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.
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

Return the newly activated mode, or the full renewed status dict after a reset.

This method is a coroutine.


pyotgw.set_outside_temp(self, temp, timeout=OTGW_DEFAULT_TIMEOUT)

Set the outside temperature. Configure 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. This method supports the following arguments:

  • temp The outside temperature to provide to the gateway.
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

Returns the accepted value on success, - if a previously configured value has been cleared or None on failure.

This method is a coroutine.


pyotgw.set_response(self, data_id, data, timeout=OTGW_DEFAULT_TIMEOUT)

Not implemented yet. Configure a response to send back to the thermostat instead of the response produced by the boiler. This method supports the following arguments:

  • data_id The data-ID for which the response should be set. Values from 1 to 255 are allowed.
  • data A list of one or two hex byte values to be passed along with the data_id.
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

Returns the data ID for which the response was set, or None on failure.

This method is a coroutine.


pyotgw.set_setback_temp(self, sb_temp, timeout=OTGW_DEFAULT_TIMEOUT)

Set the setback temperature. Configure the setback temperature to use in combination with the GPIO functions home(5) and away(6). This method supports the following arguments:

  • sb_temp The new setback temperature.
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

Returns the new setback temperature, or None on failure.

This method is a coroutine.


pyotgw.set_target_temp(self, temp, temporary=True, timeout=OTGW_DEFAULT_TIMEOUT)

Set the room setpoint. Configure the thermostat setpoint and specify whether or not it may be overridden by a programmed change. This method supports the following arguments:

  • temp The new room setpoint. Will be formatted to 1 decimal.
  • temporary Whether or not the thermostat program may override the room setpoint. Either True or False. Defaults to True.
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

Returns the newly accepted room setpoint, or None on failure.

This method is a coroutine.


pyotgw.set_ventilation(self, pct, timeout=OTGW_DEFAULT_TIMEOUT)

Set the ventilation setpoint. Configure a ventilation setpoint override value (0-100%). This method supports the following arguments:

  • pct The new ventilation setpoint. Must be between 0 and 100.
  • timeout The timeout for the request. Defaults to OTGW_DEFAULT_TIMEOUT (3 seconds).

Return the newly accepted value, or None on failure.

This method is a coroutine.


pyotgw.subscribe(self, coro)

Subscribe to status updates from the Opentherm Gateway. Can only be used after pyotgw.connect(). The subscribed coroutine must have the following signature:

async def coro(status)

Where status will be the full status dict containing the last known information from the OpenTherm Gateway. This method supports the following arguments:

  • coro A coroutine which will be called whenever a status change occurs.

Returns True on success, False if not connected or if the coroutine is already subscribed.


pyotgw.unsubscribe(self, coro)

Unsubscribe from status updates from the Opentherm Gateway. Can only be used after pyotgw.connect(). The supplied coroutine must have been subscribed with pyotgw.subscribe() before. This method supports the following arguments:

  • coro The coroutine which will be unsubscribed.

Returns True on success, False if not connected or if the coroutine was not subscribed before.


Usage Example

import asyncio
from pyotgw import pyotgw

PORT = '/dev/ttyUSB0'


async def print_status(status):
  """Receive and print status."""
  print("Received a status update:\n{}".format(status))


async def connect_and_subscribe():
  """Connect to the OpenTherm Gateway and subscribe to status updates."""

  # Create the object
  gw = pyotgw()

  # Connect to OpenTherm Gateway on PORT
  status = await gw.connect(asyncio.get_event_loop(), PORT)
  print("Initial status after connecting:\n{}".format(status))

  # Subscribe to updates from the gateway
  if not gw.subscribe(print_status):
    print("Could not subscribe to status updates.")

  # Keep the event loop alive...
  while True:
    await asyncio.sleep(1)


# Set up the event loop and run the connect_and_subscribe coroutine.
loop = asyncio.get_event_loop()
try:
  loop.run_until_complete(connect_and_subscribe())
except KeyboardInterrupt:
  print("Exiting")

About

A library to interface with the OpenTherm Gateway through serial or network connection.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Python 100.0%