Profile
Back to NewsBack
GitHub Trending 15 min
Reader Mode
rvdbreemen/OTGW-firmware: A ESP8266 devkit firmware for the Nodoshop version of the Opentherm Gateway (OTGW)

rvdbreemen/OTGW-firmware: A ESP8266 devkit firmware for the Nodoshop version of the Opentherm Gateway (OTGW)

20 hours ago

OTGW-firmware v2.0.0

Join the Discord chat</a> GitHub release</a> License: GPLv3</a>

Disclaimer: v2.0.0-beta.130 is a beta of the 2.0.0 line. It is not a stable release. It has had alpha and beta testing on a small group of units, but not yet the long field runs a stable release needs. Expect bugs, save your settings before you flash, and read the beta.130 release notes first, including the known issues.
> If you need a gateway that just works, stay on the 1.x line for now: the otgw-1.x.x branch and the published releases.

OTGW-firmware turns the NodoShop OpenTherm Gateway into a networked smart heating controller. It runs on an ESP32-S3 (LOLIN S3 Mini or S3 Mini Pro) in the traditional NodoShop OTGW with the PIC co-processor, monitors the OpenTherm bus between your thermostat and boiler, and connects your heating system to your home automation platform via MQTT, a browser-based web interface and a REST API. That combination is the supported hardware.

A prototype ESP32 board that drives OpenTherm directly, without a PIC, also exists. It is a prototype and nothing more at this time.


What's New in v2.0.0

Version 2.0.0 is a major platform release. It targets the ESP32-S3 in the traditional OTGW with PIC; the ESP8266 is no longer a 2.0.0 build target. If you are coming from a v1.x ESP8266 build, see Migrating from ESP8266 (1.x).

Highlights

  • ESP32-S3 platform: an asynchronous web server and FreeRTOS on a LOLIN S3 Mini (or S3 Mini Pro) in place of the old Wemos D1 mini. One firmware image (esp32-combo) detects the board at boot.
  • v2 web UI: the only web UI in 2.0.0. Live value table, graph with history, help text for every setting, SAT page. The File Explorer stays as the recovery page.
  • Firmware updates over WiFi: a small safeboot updater sits next to the firmware. If an update fails or a new firmware crashes in its first 30 seconds, the unit returns to safeboot and stays reachable. Units on an older flash layout need one USB migration first.
  • SAT (Smart Autotune Thermostat), experimental and opt-in: an embedded heating controller, off by default. See SAT.
  • Home Assistant: MQTT auto-discovery for the OpenTherm values, SAT, sensors and diagnostics, including SAT power, energy and gas estimates for the Energy dashboard.
  • Works behind a reverse proxy, including a Home Assistant sidebar panel (ingress). Guide: docs/guides/REVERSE_PROXY_AND_HA_INGRESS.md.
  • BLE room sensors: Xiaomi LYWSD03MMC sensors (BTHome v2) are read passively over Bluetooth LE and feed SAT and Home Assistant.
  • Diagnostics: a capture tool (launchers for Windows and for Linux/macOS) that records telnet, MQTT, the crash log and raw OpenTherm frames in one upload file, and a crash log with core-dump details after a panic.
  • Relicensed to GNU GPLv3 (was MIT).
Breaking changes: 2.0.0 changes MQTT topics, REST fields and settings compared with 1.x. Check your Home Assistant automations, Node-RED flows and scripts against the breaking changes in the release notes before you upgrade.

Features at a Glance

Core features

  • Full OpenTherm bus monitoring: all 80+ message IDs decoded in real time
  • MQTT integration with Home Assistant auto-discovery
  • Web interface: live OT log, real-time graphs, dark/light theme, settings panel
  • REST API v2 with consistent JSON and proper HTTP status codes
  • SAT (Smart Autotune Thermostat): weather-compensated PID heating controller, experimental and opt-in
  • DS18B20 Dallas temperature sensors with custom labels (up to 16)
  • S0 pulse-counting energy meter
  • Optional SSD1306 OLED display (128x64, I2C)
  • Firmware and filesystem updates over WiFi through a safeboot updater
  • TCP serial bridge on port 25238 for OTmonitor and the HA built-in integration (off by default)
  • Telnet debug log on port 23
  • Webhook callbacks on OpenTherm status bit changes
  • Triple-reset Wi-Fi credential recovery
  • Optional HTTP Basic Auth for settings and maintenance endpoints

Hardware Support

Platform overview

The supported hardware is the NodoShop OTGW with the PIC co-processor and an ESP32-S3 (LOLIN S3 Mini) in the module socket:

| Feature | ESP32-S3 OTGW with PIC | |---|---| | OpenTherm via PIC co-processor | Yes (required) | | Wi-Fi | Yes | | OLED display | Yes | | SAT thermostat | Yes | | Dallas sensors | Yes | | S0 pulse counter | Yes |

A prototype ESP32 board with onboard OpenTherm also exists. It is a prototype and nothing more at this time.

Migrating from ESP8266 (1.x)

Firmware v1.x ran on the ESP8266 module that shipped on earlier NodoShop OTGW boards:

| NodoShop OTGW version | ESP8266 module (v1.x) | |---|---| | 1.x through 2.0 | NodeMCU ESP8266 | | 2.3 and later | Wemos D1 mini ESP8266 |

The ESP8266 is no longer a 2.0.0 build target. To move an existing OTGW to v2.0.0, swap the Wemos D1 mini ESP8266 for a LOLIN S3 Mini (ESP32-S3) drop-in: it keeps the same OTGW board and PIC co-processor, and the firmware builds for it from the same source tree. Settings files from v1.3.x load without modification.

This ESP32-S3 plus PIC combination is what the firmware supports.


SAT: Smart Autotune Thermostat

SAT is experimental and off by default. When you switch it on, it takes over the control setpoint of your boiler, and other channels can no longer send central heating commands. The setup wizard asks you to confirm that first. SAT behaviour can still change between builds; see the release notes. Without SAT, the gateway is a transparent OpenTherm gateway, as in 1.x.

SAT is an embedded heating controller that runs entirely on the device, a port of the SAT Home Assistant integration. It replaces the room thermostat's role in controlling the boiler: it computes the boiler flow temperature from the outdoor temperature and the room temperature error, and keeps your home at the target temperature without needing Home Assistant or any external controller in the control loop.

What SAT does

SAT combines a weather-compensated heating curve with a PID controller. The heating curve calculates a base flow setpoint from the outdoor temperature using a configurable coefficient. The PID loop adds a correction on top, based on the difference between actual and target room temperature. The PID gains follow from the heating curve coefficient. A daily self-tune (on by default, can be switched off) moves the coefficient by 0.1 when the last 3 days show the curve is clearly too low or too high.

Key capabilities

  • Weather compensation: configurable heating curve coefficient (0.1 to 5.0), a daily self-tune of that coefficient, and a curve recommendation based on error statistics
  • PID control: proportional + integral + derivative correction on top of the heating curve
  • Two control modes: continuous modulation (direct boiler modulation) and PWM flame cycling (on/off duty cycle)
  • Heating system types: radiators, underfloor heating, heat pump
  • Six presets: comfort, eco, away, sleep, activity, home, each with a configurable target temperature
  • Multi-zone room temperature: averages readings from up to four sources (OT, MQTT, BLE, Dallas)
  • BLE room sensor (ESP32 only): reads temperature and humidity from a Xiaomi LYWSD03MMC via BTHome v2
  • Solar gain compensation: detects solar gain from indoor temperature rise rate and sun elevation angle; reduces setpoint to prevent overheating
  • Summer Simmer Index: calculates perceived outdoor heat; suppresses heating when the index stays above a threshold
  • Summer suppression: independent outdoor-temperature-based heating cutoff with configurable duration threshold
  • Pressure monitoring: tracks system pressure; raises alarm on low pressure or fast pressure drop
  • OPV calibration: finds the boiler's Overpressure Valve temperature so SAT stays below it
  • Six safety layers: flame health, CH circuit sync, setpoint mismatch, pressure, cycle classification, overshoot detection
  • Open-Meteo integration: optional free weather API for outdoor temperature when no local source is available

Quick start

  1. Open the OTGW web interface and go to SAT in the navigation.
  2. Start the setup wizard. Read and confirm the "Before you enable SAT" step.
  3. Select your heating system type (radiators / underfloor / heat pump) and set your target room temperature.
  4. Enter your boiler capacity in kW.
  5. Set an initial heating curve coefficient (start with 1.0 for radiators, 0.6 for underfloor; the curve recommendation and the self-tune guide further tuning).
  6. Save. SAT takes over the flow setpoint immediately. Please share a capture log with us if you run SAT: see the release notes, "Capture tool".
For detailed setup including OPV calibration and Home Assistant automation examples, see the SAT integration guide.

Home Assistant integration

When SAT is enabled and MQTT is configured, Home Assistant receives:

  • A climate entity with target temperature control and heat/off mode selection
  • 40+ sensor and binary_sensor entities for SAT state, diagnostics, and settings
  • BLE sensor entities (ESP32 only): temperature and humidity per sensor
Commands via MQTT or the REST API (/api/v2/sat/*) control all SAT parameters at runtime.

| Reference | Link | |---|---| | MQTT topics | docs/api/MQTT.md | | Full SAT topic list | docs/api/MQTT.md, section SAT | | REST API | docs/api/openapi.yaml | | OPV calibration guide | backlog/docs/doc-2 - sat-opv-calibration.md | | Preset configuration | backlog/docs/doc-4 - sat-preset-configuration.md |


Quick Start

1. Flash the firmware

Unpack the release zip (OTGW-firmware---flash.zip), connect the unit over USB and run the flash tool from it:

flash_otgw.bat            # Windows
./flash_otgw.sh           # Linux/macOS

Without options this is a factory install: it erases the flash and writes firmware and filesystem. Units that already run 2.0.0 are updated over WiFi; units on an older flash layout need one USB migration first. See docs/guides/WIFI_FIRMWARE_UPDATE.md. To build from source, see docs/guides/BUILD.md.

2. Connect to Wi-Fi

On first boot the device creates an access point named -. Connect to it. A captive portal opens where you enter your home Wi-Fi credentials. On an ESP32 board with a W5500 and an Ethernet cable plugged in, wired Ethernet is used directly and the Wi-Fi setup is optional.

3. Open the Web UI

Navigate to http:/// or http://otgw2.local/. The dashboard shows the live OpenTherm log, temperatures, and boiler status.

4. Configure MQTT

Go to Settings and fill in your MQTT broker details. Enable HA Discovery. Click Save. Home Assistant discovers the device within seconds.

5. Check Home Assistant

Go to Settings > Devices and Services > MQTT. The OTGW device appears with its entities already created and ready to use.


Setting Up MQTT with Home Assistant

Prerequisites

  • Home Assistant with the MQTT integration installed (Settings > Devices and Services > MQTT).
  • An MQTT broker running (Mosquitto add-on, or an external broker).
  • Your OTGW device connected to the same network.

Step 1: Configure MQTT in the web UI

Open http:/// and go to Settings.

| Setting | Description | Example | |---|---|---| | MQTT Broker | IP or hostname of your broker | 192.168.1.100 | | MQTT Port | Broker port | 1883 | | MQTT User | Broker username | mqttuser | | MQTT Password | Broker password | (your password) | | MQTT Top Topic | Prefix for all published topics | OTGW | | MQTT Unique ID | Identifier for this device in HA | otgw | | HA Discovery | Enables auto-discovery payloads | checked |

Step 2: Verify in Home Assistant

After saving, Home Assistant discovers the OTGW device. Go to Settings > Devices and Services > MQTT to see all entities: temperatures, setpoints, modulation, flame, DHW, faults, and more. No manual YAML required.

Step 3: Tune the publish interval

By default, MQTT Publish On-Change (Settings > MQTT) is enabled: the gateway publishes immediately when an OpenTherm value changes and republishes unchanged values every 60 seconds as a heartbeat. This keeps data fresh while avoiding the high MQTT traffic of publishing every repeated OpenTherm frame.

With MQTT Publish On-Change enabled the gateway will publish immediately when a value changes and re-publish unchanged values once per MQTT Interval as a heartbeat (so Home Assistant does not mark sensors as unavailable). A value of 10-60 seconds is a good starting point. Unticking MQTT Publish On-Change restores legacy behaviour: every OpenTherm frame is published as it arrives. When upgrading from a release that published every frame (MQTTinterval=0), the gateway migrates that setting once to 60 seconds with Publish On-Change enabled.

Step 4: Send commands from Home Assistant

The gateway subscribes to a command topic. Structure:

<TopTopic>/set/<UniqueId>/<command>

Common commands:

| Command | Description | Example payload | |---|---|---| | setpoint | Temporary temperature override (TT) | 21.5 | | constant | Constant temperature override (TC) | 22.0 | | outside | Override outside temperature (OT) | 15.5 | | hotwater | DHW control: 0=off, 1=on, P=push, A=auto | 1 | | maxchsetpt | Max CH water setpoint (SH) | 60 | | maxdhwsetpt | Max DHW setpoint (SW) | 55 |

Example: sync outdoor temperature from another HA sensor:

automation:
  - alias: "Sync Outside Temperature to OTGW"
    trigger:
      - platform: state
        entity_id: sensor.outdoor_temperature
    action:
      - service: mqtt.publish
        data:
          topic: "OTGW/set/otgw/outside"
          payload: "{{ states('sensor.outdoor_temperature') }}"

More examples: Outside Temperature Override | Hot Water Control

Alternative: built-in HA OpenTherm Gateway integration

The Home Assistant OpenTherm Gateway integration can connect directly via the TCP serial bridge without MQTT. The bridge is off by default: switch on "Legacy TCP port 25238" in the OTGW settings first.

socket://<device-ip>:25238

This provides basic thermostat control but does not expose the full range of data that MQTT auto-discovery covers.


Connectivity Summary

| Port | Protocol | Purpose | |---|---|---| | 80 | HTTP | Web UI and REST API | | 80 (/ws) | WebSocket | Live OpenTherm log stream | | 23 | Telnet | Debug log output | | 25238 | TCP | OTGW serial bridge (OTmonitor, HA built-in integration); off by default, switch on "Legacy TCP port 25238" | | 1883 | MQTT (outbound) | Home automation integration |

The device also exposes a Wi-Fi configuration portal (AP mode) on first boot or after triple-reset recovery.


Security Notes

The web UI and APIs are designed for use on a trusted local network. The device itself speaks plain HTTP and WebSocket only. Do not expose it directly to the internet; use a VPN for remote access. A reverse proxy works, including an HTTPS-terminating one and the Home Assistant panel (ingress): the live log then runs over wss:// through the proxy, as long as the proxy carries WebSocket. See docs/guides/REVERSE_PROXY_AND_HA_INGRESS.md.

Protected endpoints (optional)

Set an endpoint password in Settings (httppasswd) to require HTTP Basic Auth for:

  • Reading and changing device settings
  • File upload, download, and delete
  • Reboot and wireless reset
  • OTA firmware and filesystem updates
  • Webhook test
Live monitoring, sensor values, and the WebSocket stream remain open without authentication.

Documentation

| Topic | Link | |---|---| | Wiki (recommended starting point) | | | Flash guide (ESP8266, 1.x) | docs/guides/FLASH_GUIDE.md | | Firmware updates over WiFi (ESP32-S3) | docs/guides/WIFI_FIRMWARE_UPDATE.md | | Local build guide | docs/guides/BUILD.md | | REST API reference | docs/api/README.md | | OpenAPI specification | docs/api/openapi.yaml | | MQTT topic reference | docs/api/MQTT.md | | WebSocket protocol | docs/api/WEBSOCKET_FLOW.md | | Dallas sensor labels API | docs/api/DALLAS_SENSOR_LABELS_API.md | | Webhook documentation | docs/features/webhook.md | | Dallas sensor documentation | docs/features/dallas-temperature-sensors.md | | Architecture Decision Records | docs/adr/README.md | | C4 architecture context | docs/c4/c4-context.md | | Code quality checker | docs/process/EVALUATION.md | | Upgrading from 0.x | docs/upgrade-from-0.x.md | | Release notes | docs/releases/ |


Important Warnings

  • Do not flash PIC firmware over Wi-Fi using OTmonitor. This can brick the PIC microcontroller. Use the built-in PIC firmware upgrade feature in the web UI instead.
  • Dallas GPIO default changed in v1.0.0 (1.x, ESP8266): The default pin moved from GPIO 13 (D7) to GPIO 10 (SD3). If upgrading a 1.x unit from a version before v1.0.0, verify your wiring or change the setting back to 13.
  • REST API v0/v1 removed in v1.2.0: Only /api/v2/ endpoints remain. See the REST API reference.
  • MQTT topic corrections in v1.2.0: A few spelling fixes changed topic names (eletric_production to electric_production, etc.). Delete orphaned Home Assistant entities and let discovery recreate them. Details: breaking changes.
  • ESP32 OTDirect note: When OTDirect is active, the PIC UART is bypassed. Do not attempt PIC firmware upgrades while OTDirect is the active OpenTherm path.

History and Scope

The OpenTherm Gateway hardware and PIC firmware originate from Schelte Bron's OTGW project (). This firmware builds on that ecosystem by running on the ESP32 inside the NodoShop OTGW to expose the gateway's data and controls over the network.

The primary hardware target is the NodoShop OTGW with an ESP32-S3 (LOLIN S3 Mini). Earlier ESP8266 boards ran firmware v1.x; see Migrating from ESP8266 (1.x). Other boards may work, but these are the tested and supported configurations.


Community and Support

  • Discord:
  • Issues and bug reports:
  • GitHub Releases (prebuilt binaries):

Credits

Reaching v2.0.0 would not have been possible without years of community testing, feedback, and contribution. Thank you to everyone who has reported issues, pushed for features, and helped others in the Discord.

Special thanks to:

  • @hvxl (Schelte Bron) for all his work on the OTGW hardware, PIC firmware, and ESP coding, and for providing access to the PIC upgrade routines that make reliable PIC firmware flashing possible. If you want to thank Schelte for his work, head over to and donate.
  • @sjorsjuhmaniac for improving the MQTT naming convention and Home Assistant integration, and for the climate entity and OTGW device model.
  • @GeorgeZ83 for improving Home Assistant MQTT integration and climate entity support across many releases.
  • @DaveDavenport for fixing known and unknown codebase issues and making the firmware substantially more stable.
  • @DutchessNicole for improving the Web UI over multiple releases.
  • @vampywiz17 for early adoption and thorough testing.
  • @Stemplar for early issue reporting.
  • @proditaki for creating the Domoticz plugin for OTGW-firmware.
  • @tjfsteele for endless hours of testing.
  • @RobR for the S0 pulse counter implementation.
And to everyone who keeps reporting issues, pushing for more, and helping others in the community.

Buy Me a Coffee

Buy me a coffee</a>


License

GNU General Public License v3.0. See LICENSE.

Relicensed from MIT to GPLv3 on 2026-07-06. This applies to the project's own code (Robert van den Breemen, sole copyright holder); third-party vendored libraries (src/libraries/OpenTherm, src/libraries/OTGWSerial) and the LGPL-2.1-licensed portions of FSexplorer.ino keep their original licenses and copyright notices unchanged.

Chat with me