No description
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
dependabot[bot] 1e7787491d
Some checks failed
CodeQL / Analyze (push) Has been cancelled
Deploy Documentation to GitHub Pages / deploy (push) Has been cancelled
Build & Test / build (3.10) (push) Has been cancelled
Build & Test / build (3.11) (push) Has been cancelled
Build & Test / build (3.12) (push) Has been cancelled
Build & Test / build (3.13) (push) Has been cancelled
Build & Test / build (3.14) (push) Has been cancelled
Build & Test / build (3.15) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
chore(deps): update sphinx-rtd-theme requirement in /docs (#132)
Updates the requirements on [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) to permit the latest version.
- [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst)
- [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/3.0.0...3.1.0)

---
updated-dependencies:
- dependency-name: sphinx-rtd-theme
  dependency-version: 3.1.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Andy Loughran <andy@zrmt.com>
2026-10-28 08:14:19 +00:00
.devcontainer ci(devops): modernize workflows to checkout@v4 and setup-uv@v5, configure flake8, and update devcontainer 2026-10-12 22:27:35 +01:00
.github ci(actions): bump the actions group with 6 updates 2026-10-28 08:11:00 +00:00
doc merge: synchronize main with serial support, pin workflow action SHAs, and canonicalize ADRs 2026-10-13 19:59:53 +01:00
docs chore(deps): update myst-parser requirement in /docs 2026-10-28 08:12:27 +00:00
examples merge: synchronize main with serial support, pin workflow action SHAs, and canonicalize ADRs 2026-10-13 19:59:53 +01:00
heatmiserv3 feat: add bus arbitration, DCB caching, ADR 0004, RTD config, and 0.5C twin quantization 2026-10-13 22:17:34 +01:00
heatmiserV3.egg-info Switched to version 2 to match new package name 2024-01-28 19:04:02 +00:00
tests feat: add bus arbitration, DCB caching, ADR 0004, RTD config, and 0.5C twin quantization 2026-10-13 22:17:34 +01:00
.flake8 ci(devops): modernize workflows to checkout@v4 and setup-uv@v5, configure flake8, and update devcontainer 2026-10-12 22:27:35 +01:00
.gitignore feat: add bus arbitration, DCB caching, ADR 0004, RTD config, and 0.5C twin quantization 2026-10-13 22:17:34 +01:00
.pre-commit-config.yaml [StepSecurity] Apply security best practices 2026-10-27 20:59:01 +00:00
.readthedocs.yaml feat: add bus arbitration, DCB caching, ADR 0004, RTD config, and 0.5C twin quantization 2026-10-13 22:17:34 +01:00
CHANGELOG.md chore(release): bump version to 3.0.0 and update changelog 2026-10-13 22:32:01 +01:00
CONTRIBUTING.md chore: remove protocol PDF binary, add *.pdf to .gitignore, and update spec link 2026-10-13 20:59:03 +01:00
LICENSE.TXT Spell check 2015-12-09 09:16:55 +00:00
pyproject.toml Update toml 2026-10-26 21:58:08 +00:00
README.md fix(deps): update importlib-resources requirement to >=7.1.0,<8 and docs URL casing 2026-10-13 22:52:32 +01:00
uv.lock UpdateD 2026-10-26 22:00:00 +00:00

heatmiserv3

Build Status Documentation Python Version Packaging License: MIT Code Style: Flake8

Caution

Having lost access to physical Heatmiser hardware a few years ago, the maintainer can no longer perform real-world hardware regression testing.

If you are interested in taking over maintenance or migrating the repository to a dedicated community organization, please reach out or open an issue! For architectural decisions made since losing hardware access, see the ADRs in docs/adrs/.


📖 View the Complete Protocol & Library Documentation Website

The documentation includes an interactive Visual Test Harness (Digital Twin) simulating backlit LCDs, relay contact states, underfloor overheat cutouts, environment sliders, and live RS485 bytecode packet inspection.


Overview

heatmiserv3 is a Python library to interact with Heatmiser Thermostats and Timing Switches communicating over the Heatmiser V3 RS485 serial-over-IP or serial bus protocol.

It provides high-level object models (HeatmiserThermostat, TM1Thermostat) as well as network connection multiplexing (HeatmiserUH1) to read Data Control Blocks (DCBs), inspect telemetry, adjust setpoints, and configure heating/timing schedules.

sequenceDiagram
    autonumber
    participant App as Home Assistant / Python App
    participant UH1 as HeatmiserUH1 Bridge
    participant RS485 as RS485 / Network Bus
    participant Stat as Heatmiser Slave (PRT / TM1)

    App->>UH1: Initialise connection (socket / serial)
    App->>UH1: Register thermostat (address 1, model "prt")
    App->>Stat: read_dcb() / get_target_temp()
    Stat->>UH1: Form READ frame + CRC16
    UH1->>RS485: Transmit binary bytecode
    RS485->>Stat: Bytecode delivered
    Stat-->>RS485: Respond with DCB frame (9-byte header + DCB payload + CRC)
    RS485-->>UH1: Raw bytes received
    UH1-->>Stat: Verify frame length & CRC16 checksum
    Stat-->>App: Parsed DCB attributes (temp, status, relays)

Supported Hardware

Category Models Protocol Features
Thermostats PRT, PRT-E, PRT-HW, DT, DT-E Full DCB read, setpoint modification, frost protection, floor temperature limit monitoring
Timing Switches TM1, TM1-N Relay switching, holiday hours, countdown timer, 5/2 & 7-day switching schedules
Wiring Centres UH1 RS485 serial-over-IP multiplexing for up to 32 chained thermostats

Installation

Using pip:

pip install heatmiserv3

Using uv:

uv add heatmiserv3

Quick Start

Interfacing with a PRT Thermostat via UH1

from heatmiserv3 import connection, heatmiser

# 1. Connect to Heatmiser UH1 wiring centre over TCP/IP or local serial device:
uh1 = connection.HeatmiserUH1("192.168.1.57", 8068)
# Alternatively, connect via a direct local RS485 serial adapter:
# uh1 = connection.HeatmiserUH1(dev="/dev/ttyACM0")

# 2. Register a thermostat attached to the UH1 bus at RS485 address 1
thermo1 = heatmiser.HeatmiserThermostat(1, "prt", uh1)

# 3. Read telemetry
print(f"Room Temperature: {thermo1.get_floor_temp()}°{thermo1.get_temperature_format()}")
print(f"Target Temperature: {thermo1.get_target_temp()}°C")
print(f"Heating Active: {thermo1.get_heating() == 1}")

# 4. Modify setpoints (with built-in range validation)
success = thermo1.set_target_temp(21)
if success:
    print("Target temperature updated to 21°C")

Interfacing with a TM1 Timing Switch

from heatmiserv3 import connection, heatmiser

uh1 = connection.HeatmiserUH1("192.168.1.57", 8068)
timer = heatmiser.TM1Thermostat(2, uh1)

# Check timer status
print(f"On/Off: {timer.get_on_off()}")
print(f"Program Mode: {timer.get_program_mode()}")

# Override timer ON
timer.set_timer_state(1)

Architecture Decision Records (ADRs)

Key architectural decisions are documented under docs/adrs/:

Development & Testing

This project uses uv and hatchling.

# Clone the repository
git clone https://github.com/andylockran/heatmiserv3.git
cd heatmiserv3

# Install dependencies into virtualenv
uv sync

# Run tests and verify >90% coverage gate
uv run pytest --cov=heatmiserv3 --cov-report=term-missing

# Run code style and lint checks
uv run flake8

# Build source distribution and binary wheel
uv build

See CONTRIBUTING.md for contribution guidelines.

Origin & Credits

This library originated from reverse engineering and protocol implementation work carried out by Neil Trimboy in 2011 on Google Code. It has been maintained and modernized by Andy Loughran and community contributors.