Hi everyone,
I would like to share my configuration for integrating Lambda Heat Pumps (https://www.lambda-wp.at/) into Home Assistant. Since Lambda uses a standard Modbus TCP protocol, we can achieve a deep integration without any extra hardware, allowing for real-time monitoring of efficiency (COP), temperatures, and operating states.
Prerequisites
- Modbus TCP Enabled: Ensure Modbus TCP is activated in your Lambda controller settings.
- Static IP: It is highly recommended to set a DHCP Reservation (Static IP) for your heat pump in your router settings to ensure Home Assistant doesn’t lose the connection after a reboot.
- Documentation: You can find the official Modbus register map here: Lambda Modbus Protocol (PDF)
Configuration
The setup is split into two parts: the Modbus sensors and Template sensors for calculated values like “Spread” (Spreizung) and human-readable states.
1. Modbus Sensor Setup (modbus.yaml or configuration.yaml)
This block defines the connection and pulls the raw data from the registers.
# Example configuration for Modbus TCP
modbus:
- name: lambda_heatpump
type: tcp
host: YOUR_HEAT_PUMP_IP # Replace with your actual IP address, e.g., 192.168.1.133
port: 502
delay: 2
timeout: 5
sensors:
# --- Status & Environment ---
- name: "Lambda Operating State"
unique_id: lambda_op_state_fixed
address: 1
input_type: holding
scan_interval: 30
- name: "Lambda Ambient Temp"
unique_id: lambda_ambient_temp_fixed
address: 2
input_type: holding
data_type: int16
scale: 0.1
precision: 1
unit_of_measurement: "°C"
device_class: temperature
scan_interval: 60
# --- Temperatures & Flow ---
- name: "Lambda Flow Common"
unique_id: lambda_flow_common_fixed
address: 5002
input_type: holding
data_type: int16
scale: 0.1
precision: 1
unit_of_measurement: "°C"
device_class: temperature
scan_interval: 45
- name: "Lambda Return EG"
unique_id: lambda_return_eg_fixed
address: 5003
input_type: holding
data_type: int16
scale: 0.1
precision: 1
unit_of_measurement: "°C"
device_class: temperature
scan_interval: 45
- name: "Lambda Return NG"
unique_id: lambda_return_ng_fixed
address: 5103
input_type: holding
data_type: int16
scale: 0.1
precision: 1
unit_of_measurement: "°C"
device_class: temperature
scan_interval: 45
- name: "Lambda Return OG"
unique_id: lambda_return_og_fixed
address: 5203
input_type: holding
data_type: int16
scale: 0.1
precision: 1
unit_of_measurement: "°C"
device_class: temperature
scan_interval: 45
# --- Efficiency & Power ---
- name: "Lambda COP Internal"
unique_id: lambda_cop_intern_fixed
address: 1013
input_type: holding
data_type: int16
scale: 0.01
precision: 2
unit_of_measurement: "COP"
state_class: measurement
scan_interval: 60
nan_value: 0.0
- name: "Lambda Power Input"
unique_id: lambda_power_input_fixed
address: 1012
input_type: holding
data_type: int16
scale: 1
precision: 0
unit_of_measurement: "W"
device_class: power
state_class: measurement
scan_interval: 60
- name: "Lambda Actual Heating Capacity"
unique_id: lambda_actual_heating_capacity_fixed
address: 1011
input_type: holding
data_type: int16
scale: 0.1
precision: 1
unit_of_measurement: "kW"
device_class: power
state_class: measurement
scan_interval: 60
2. Template Sensors (template.yaml)
These sensors calculate the temperature delta (spread) between flow and return for different floors and translate the numeric operating state into readable text.
- sensor:
# Calculation of temperature spread for different zones
- name: "Spread Ground Floor (EG)"
unique_id: spreizung_eg
unit_of_measurement: "K"
state: >
{% set flow = states('sensor.lambda_flow_common') | float(none) %}
{% set return = states('sensor.lambda_return_eg') | float(none) %}
{% if flow is not none and return is not none %}
{% set diff = (flow - return) | round(1) %}
{% if -20 < diff < 60 %} {{ diff }} {% else %} {{ states('sensor.spreizung_eg') | float(0) }} {% endif %}
{% else %} 0.0 {% endif %}
- name: "Spread Next Floor (NG)"
unique_id: spreizung_ng
unit_of_measurement: "K"
state: >
{% set flow = states('sensor.lambda_flow_common') | float(none) %}
{% set return = states('sensor.lambda_return_ng') | float(none) %}
{% if flow is not none and return is not none %}
{% set diff = (flow - return) | round(1) %}
{% if -20 < diff < 60 %} {{ diff }} {% else %} {{ states('sensor.spreizung_ng') | float(0) }} {% endif %}
{% else %} 0.0 {% endif %}
- name: "Spread Upper Floor (OG)"
unique_id: spreizung_og
unit_of_measurement: "K"
state: >
{% set flow = states('sensor.lambda_flow_common') | float(none) %}
{% set return = states('sensor.lambda_return_og') | float(none) %}
{% if flow is not none and return is not none %}
{% set diff = (flow - return) | round(1) %}
{% if -20 < diff < 60 %} {{ diff }} {% else %} {{ states('sensor.spreizung_og') | float(0) }} {% endif %}
{% else %} 0.0 {% endif %}
# Translation of Operating Mode
- name: "Lambda Operating Mode Text"
unique_id: lambda_mode_text_template
state: >
{% set modes = {0: 'OFF', 1: 'AUTOMATIC', 2: 'MANUAL', 3: 'ERROR'} %}
{{ modes.get(states('sensor.lambda_operating_state') | int(0), 'Unknown') }}
icon: >
{% set state = states('sensor.lambda_operating_state') | int(0) %}
{% if state == 0 %} mdi:power-off
{% elif state == 1 %} mdi:refresh-auto
{% elif state == 2 %} mdi:hand-pointing-up
{% elif state == 3 %} mdi:alert-octagon
{% else %} mdi:help-circle {% endif %}
# Stable COP sensor for clean Long Term Statistics graphing
- name: "Lambda COP Graph"
unique_id: cop_grafik_stable
unit_of_measurement: "COP"
state_class: measurement
state: >
{{ states('sensor.lambda_cop_internal') | float(0.0) }}
availability: >
{{ true }}
Features of this setup
- Resilience: The template sensors include safety checks to prevent unrealistic spikes in your graphs if a Modbus read fails.
- Human Readable: Converts numeric codes (0, 1, 2) into clear status text (OFF, AUTO, etc.).
- Calculated Metrics: Automatically calculates the temperature delta (Spread), which is crucial for balancing your heating circuits.
I hope this helps anyone looking to integrate their Lambda system!