TapHome

EMS-ESP Heat Pump (Bosch, Buderus, IVT)

Packet Parser → HTTP
Submitted by
Last updated: 10. 2026

Requires external gateway

BBQKees Electronics Gateway E32 V2 (EMS-ESP 3.8.6 firmware) — product page

This device supports mDNS

Instead of using an IP address, you can reach the device at:

ems-esp.local

Replace {MAC} with your device's MAC address (uppercase, no colons).

TapHome supports mDNS — using a hostname is more reliable than a static IP.

EMS-ESP Heat Pump (Bosch, Buderus, IVT)

The EMS-ESP Heat Pump template connects TapHome to a Bosch, Buderus or IVT heat pump through an EMS-ESP gateway — a BBQKees Electronics Gateway E32 V2 that runs the open-source EMS-ESP firmware and plugs into the EMS bus of the heat pump. TapHome talks to the gateway over its local HTTP REST API (port 80, JSON); no cloud connection is needed. In EMS-ESP the heat pump appears as device type boiler and its controller as device type thermostat.

The template reads outdoor, flow, return, room and hot water temperatures, the compressor status, the compressor power and the energy counters. With an access token it also sets the operating mode of heating circuit 1 (including cooling), the room and cooling setpoints and the hot water setpoint.

Community template — not yet tested with TapHome. The template was generated in the TapHome portal and written against EMS-ESP 3.8.6; it has not been verified on a real installation yet. Get it from the TapHome portal: EMS-ESP Heat Pump — community template (download the XML — no sign-in needed — and import it as a new module).

Compatible heat pumps and controllers

Two things decide whether a heat pump works with this template: EMS-ESP must support the heat pump, and the heat pump and its controller must report the values the template reads.

Heat pumps covered by the template:

  • Bosch Compress 6000AW, Hybrid 3000-7000iAW
  • Buderus WLW166i, WLW176i, WLW196i, WSW196i
  • CS5800i, CS6800i
  • Enviline, SupraEco, Geo 5xx
  • IVT AirX and Geo with a Rego 2000 or Rego 3000 controller — reported by EMS-ESP users, not on the official EMS-ESP list of supported heat pumps

The gateway works with the EMS, EMS Plus (EMS+), EMS2 and Heatronic 3 bus variants.

Which values a given unit reports is not documented per model. The Devices page of the EMS-ESP web interface shows only entities that have a value; an entity that exists in EMS-ESP but has no value is supported by the firmware, not by the connected unit. The same list is available at http://<gateway-ip>/api/boiler/entities and http://<gateway-ip>/api/thermostat/entities.

Cooling needs a controller that reports hc1.hpoperatingmode. EMS-ESP registers this entity for the RC300 family (RC310, HMC310, Rego 2000 / 3000) and the BC400 family; whether a specific controller actually sends it is not documented. The UI800 reports it at the thermostat top level (/api/thermostat/hpoperatingmode) instead of under heating circuit 1, so the operating mode device — and with it cooling — does not work with UI800.

Hardware connection

The BBQKees Gateway E32 V2 KIT contains the gateway, a 150 cm EMS service cable, a 100 cm EMS screw terminal cable, an EMS service port adapter plug, a power supply (12 V DC barrel jack or 5 V USB-C, depending on the production batch) and a JST ZH cable for own DS18B20 temperature sensors. The gateway connects to the heat pump in one of three ways:

Connection on the heat pumpCablePower
EMS service jack (3.5 mm)150 cm EMS service cablefrom the service jack
EMS service jack (3.5 mm)150 cm EMS service cableexternal power supply
EMS bus screw terminals100 cm EMS screw terminal cableexternal power supply (12 V DC or 5 V USB-C)

The service jack is an option only when the heat pump has one. Gateways sold from summer 2025 onward accept both types of power supply. The BBQKees EMS Gateway Wiki shows how to connect the gateway to a specific boiler or heat pump.

  • Network: Ethernet (RJ45) or Wi-Fi. EMS-ESP connects only to 2.4 GHz WPA2 Wi-Fi networks, not to 5 GHz.
  • Firmware: EMS-ESP. The Gateway E32 V2 (sold from January 2024) has PSRAM and uses the ESP32-16MB+ firmware variant. The firmware is updated in the EMS-ESP web interface under Settings → Version.

Configuration

First-time setup of EMS-ESP
  1. On the first start EMS-ESP opens a Wi-Fi access point ems-esp (WPA password ems-esp-neo). A gateway on Ethernet is reachable on the IP address the router assigned to it.
  2. Sign in with the default user admin / admin and change the password.
  3. Connect the gateway to the home network in Settings → Network (Wi-Fi or Ethernet).
  4. Reserve a fixed IP address for the gateway in the router (DHCP reservation) — the template addresses the gateway by its IP address.
EMS-ESP settings that matter
  • Temperatures in °C — keep “Convert temperature values to Fahrenheit” off in Settings → Application. The module checks this every 60 s and shows an error when EMS-ESP reports °F.
  • Boolean Format, Enum Format and Language do not matter. The template reads the index and bool keys of the EMS-ESP entity detail, which do not depend on these settings, and writes the English option texts, which EMS-ESP accepts in every language.
  • Firmware 3.8 — the module shows a warning when the gateway reports a version outside the 3.8 series. Entity names used by the template changed in 3.7.0 (ww → nested dhw) and 3.7.2 (remoteseltemp → cooltemp); between 3.8.0 and 3.8.6 they did not change.
Access token for writes

Reading needs no authentication. Writing — operating mode, room, cooling and hot water setpoints — needs the EMS-ESP access token of a user with admin rights:

  1. Open the EMS-ESP web interface → Settings → Security → Manage Users.
  2. Click the key icon of a user with admin rights and copy the token. The token has no expiry date.
  3. Paste the token into the AccessToken import parameter when importing the template.

Without a token the integration is read-only and every write ends in error 401. Do not switch on “Bypass Access Token authorization on API calls” in EMS-ESP instead — it makes the API open, and the EMS-ESP documentation does not recommend it.

Import parameters
ParameterDescription
IpAddressIP address of the EMS-ESP gateway
AccessTokenEMS-ESP access token of an admin user — needed only for writes; leave it empty for a read-only integration

Device capabilities

Heating circuit 1
  • Heat Pump Operating Mode — Off, Auto, Heating or Cooling for heating circuit 1. This is the only way to switch the heat pump to cooling in this template (see the controller limits above).
  • Room Thermostat — current and selected room temperature of heating circuit 1 as reported by the controller. The setpoint range is 0–30 °C in 0.5 °C steps.
  • Cooling Temperature — cooling temperature setting of heating circuit 1, readable and writable from −1 to 30 °C in 0.5 °C steps.

The room thermostat device is limited to 0–30 °C. The cooling temperature is sent to EMS-ESP unchanged, so keep it within −1 to 30 °C.

Heat pump status
  • Compressor Activity — what the compressor is doing: Off, Heating, Cooling, Hot Water, Pool, Pool Heating, Defrost or Compressor Alarm. This is a read-only status; selecting a value in TapHome has no effect.
  • Compressor Running — on/off indicator, on while the compressor runs.
Temperatures
  • Outdoor Temperature, Flow Temperature and Return Temperature as reported by the heat pump, with 0.1 °C resolution.
Energy
  • Electricity Meter — the demand is the current electrical power of the compressor (EMS-ESP reports W, TapHome shows kW); the total consumption is the total electrical energy consumption of the heat pump in kWh. The sources do not say whether this total includes the electric auxiliary heater, so the demand integrated over time does not have to match it.
  • Heat delivered [kWh] (service attribute of the electricity meter) — total heat energy delivered by the heat pump. This is thermal energy, not electricity consumption.
Domestic hot water
  • Domestic Hot Water — current and selected hot water temperature of the heat pump. The setpoint range of the device is 35–70 °C, the setpoint is sent in whole degrees and the heat pump enforces its own limits. The template uses the hot water values of the heat pump, not the hot water settings of the controller (dhw.settemp, dhw.mode).
How the template talks to EMS-ESP

Each device reads its own values with one HTTP GET per entity on /api/<device>/[hc1/|dhw/]<entity> and takes the value, index or bool key of the answer. The devices poll every 30 s (outdoor temperature and electricity meter every 60 s); the module reads /api/system/info every 60 s. Writes are HTTP POST requests with a JSON body and the access token in the Authorization: Bearer header.

EMS-ESP 3.8.3 and newer answers 429 Too Many Requests to a GET that arrives less than 50 ms after the previous API call. The template therefore waits 60 ms before each GET and retries once after 200 ms when it gets 429. Another client polling the EMS-ESP API at the same time (for example a second home automation system) can still cause an occasional retry.

Why REST and not Modbus. EMS-ESP also offers Modbus TCP (since 3.7.0, only on boards with PSRAM) and MQTT. The Modbus register offsets of EMS-ESP moved between the stable releases 3.8.0 and 3.8.6, so a Modbus template would silently read other values after a firmware update of the gateway. The REST API addresses values by name — a renamed entity ends in a visible device error instead.

Troubleshooting

Device error “no value from the gateway”

The message “no value from the gateway — this controller or unit does not report it; delete this device” means the connected heat pump or controller does not report this entity. Check the Devices page of EMS-ESP or http://<gateway-ip>/api/boiler/entities and http://<gateway-ip>/api/thermostat/entities, then delete the device after the import — the other devices keep working.

Device error 404

A 404 with a message such as no 'xyz' in thermostat means that EMS-ESP does not know the entity under this path — the controller does not have it (for example hc1.hpoperatingmode on a UI800) or the firmware uses another name. unknown device means EMS-ESP has not detected a heat pump or controller of that type on the EMS bus.

Write fails with error 401

The access token is missing or wrong. Copy it again from Settings → Security → Manage Users → key icon of an admin user and enter it into the AccessToken variable of the module. The token is derived from the user name and the super user password in Settings → Security → Security Settings.

Error 429

Another client polls the EMS-ESP API at the same moment. The template already paces its own requests and retries once; reduce the polling rate of the other client if the error repeats.

Module error or warning
  • “EMS-ESP reports °F” — switch Fahrenheit off in Settings → Application.
  • “Template written for EMS-ESP 3.8.6, gateway reports …” — the gateway runs firmware outside the 3.8 series. Update EMS-ESP in Settings → Version.
Electricity meter error about nrgtotal

A unit without heat metering does not report nrgtotal. The electricity meter then shows an error and the Heat delivered attribute stays empty; power and total consumption keep working.

Gateway not reachable
  1. Check the gateway LED: 1 blue flash during boot = EMS bus not connected yet (check the cable and the EMS Tx Mode setting), 2 red flashes = network still connecting (check Settings → Network; Wi-Fi must be 2.4 GHz WPA2), steady light = EMS data is flowing.
  2. Open http://<gateway-ip>/api/system/info in a browser — if it answers, the gateway is reachable.
  3. If the IP address has changed, open the mDNS name http://ems-esp.local to find the gateway, then set a DHCP reservation in the router.
  4. Use http:// — the EMS-ESP API does not support HTTPS with self-signed certificates.

Available devices

EMS-ESP Heat Pump Module
Custom Variables
AccessToken (string)EMS-ESP access token of a user with admin rights, sent as Bearer header with every write (operating mode, setpoints); reads work without it, so an empty token gives a read-only integration
EMS-ESP web interface → Settings → Security → Manage Users → key icon of a user with admin rights; paste the token into the AccessToken import parameter. The token has no expiry date.

EMS-ESP Heat Pump

Read (module)
SLEEP(60);
VAR r := SENDHTTPREQUEST("/api/system/info");
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST("/api/system/info");
END
IF r.IsSuccess
    SystemInfo := r.Content;
    IF PARSEJSON(SystemInfo, "$.settings.fahrenheit", true) = true
        ADDERROR(1, "EMS-ESP reports °F — switch Fahrenheit off in EMS-ESP Settings → Application");
    END
    IF !ISNULL(PARSEJSON(SystemInfo, "$.system.version", true))
        VAR ver := TOSTRING(PARSEJSON(SystemInfo, "$.system.version", true));
        IF INDEXOF(ver, "3.8.") != 0
            ADDWARNING(0, "Template written for EMS-ESP 3.8.6, gateway reports " + ver);
        END
    END
ELSE
    SystemInfo := "";
    ADDERROR(0, "system/info: " + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, "$.message", true)), "", " — " + PARSEJSON(r.Content, "$.message", true)));
END
Heat Pump Operating Mode Multi-value Switch

Operating mode of heating circuit 1 — Off, Auto, Heating or Cooling; the only way to switch the heat pump to cooling, available only with controllers that report it (not UI800)

enum numeric
Values / States: Off · Auto · Heating · Cooling

Heat Pump Operating Mode

Read switch state
SLEEP(60);
VAR r := SENDHTTPREQUEST("/api/thermostat/hc1/hpoperatingmode");
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST("/api/thermostat/hc1/hpoperatingmode");
END
IF r.IsSuccess
    VAR idx := PARSEJSON(r.Content, "$.index", true);
    IF ISNULL(idx)
        ADDERROR(0, "hpoperatingmode: no value from the gateway — this controller or unit does not report it; delete this device");
        RETURN(NaN);
    END
    RETURN(TODOUBLE(idx));
ELSE
    ADDERROR(0, "hpoperatingmode: " + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, "$.message", true)), "", " — " + PARSEJSON(r.Content, "$.message", true)));
    RETURN(NaN);
END
Write switch state
VAR opttext := IF(Mu = 0, "off", IF(Mu = 1, "auto", IF(Mu = 2, "heating", "cooling")));
VAR body := "{\"value\":\"" + opttext + "\"}";
VAR r := SENDHTTPREQUEST("/api/thermostat/hc1/hpoperatingmode", "POST", body, "Content-Type: application/json", "Authorization: Bearer " + AccessToken);
IF r.IsSuccess = false
    IF r.StatusCode = 401
        ADDERROR(0, "hpoperatingmode: access token missing or wrong (EMS-ESP Settings → Security → Manage Users → key icon of an admin user)");
    ELSE
        ADDERROR(0, "hpoperatingmode write: " + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, "$.message", true)), "", " — " + PARSEJSON(r.Content, "$.message", true)));
    END
END
Room Thermostat Thermostat

Current and selected room temperature of heating circuit 1 from the heat pump controller; setpoint 0–30 °C in 0.5 °C steps

numeric Unit: °C

Room Thermostat

Read temperature
IF CurrTempHc1 = ""
    RETURN(NaN);
END
VAR v := PARSEJSON(CurrTempHc1, "$.value", true);
IF ISNULL(v)
    ADDERROR(0, "currtemp: no value from the gateway — this controller or unit does not report it; delete this device");
    RETURN(NaN);
END
RETURN(TODOUBLE(v));
Read (module)
SLEEP(60);
VAR r := SENDHTTPREQUEST("/api/thermostat/hc1/currtemp");
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST("/api/thermostat/hc1/currtemp");
END
IF r.IsSuccess
    CurrTempHc1 := r.Content;
ELSE
    CurrTempHc1 := "";
    ADDERROR(0, "currtemp: " + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, "$.message", true)), "", " — " + PARSEJSON(r.Content, "$.message", true)));
END
SLEEP(60);
r := SENDHTTPREQUEST("/api/thermostat/hc1/seltemp");
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST("/api/thermostat/hc1/seltemp");
END
IF r.IsSuccess
    SelTempHc1 := r.Content;
ELSE
    SelTempHc1 := "";
    ADDERROR(1, "seltemp: " + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, "$.message", true)), "", " — " + PARSEJSON(r.Content, "$.message", true)));
END
Read desired temperature
IF SelTempHc1 = ""
    RETURN(NaN);
END
VAR v := PARSEJSON(SelTempHc1, "$.value", true);
IF ISNULL(v)
    ADDERROR(1, "seltemp: no value from the gateway — this controller or unit does not report it; delete this device");
    RETURN(NaN);
END
RETURN(TODOUBLE(v));
Write desired temperature
VAR body := "{\"value\":" + Se + "}";
VAR r := SENDHTTPREQUEST("/api/thermostat/hc1/seltemp", "POST", body, "Content-Type: application/json", "Authorization: Bearer " + AccessToken);
IF r.IsSuccess = false
    IF r.StatusCode = 401
        ADDERROR(0, "seltemp: access token missing or wrong (EMS-ESP Settings → Security → Manage Users → key icon of an admin user)");
    ELSE
        ADDERROR(0, "seltemp write: " + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, "$.message", true)), "", " — " + PARSEJSON(r.Content, "$.message", true)));
    END
END
Cooling Temperature Variable

Cooling temperature setting of heating circuit 1, adjustable from −1 to 30 °C in 0.5 °C steps; available only with controllers that report it

numeric Unit: °C

Cooling Temperature

Read
SLEEP(60);
VAR r := SENDHTTPREQUEST("/api/thermostat/hc1/cooltemp");
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST("/api/thermostat/hc1/cooltemp");
END
IF r.IsSuccess
    VAR v := PARSEJSON(r.Content, "$.value", true);
    IF ISNULL(v)
        ADDERROR(0, "cooltemp: no value from the gateway — this controller or unit does not report it; delete this device");
        RETURN(NaN);
    END
    RETURN(TODOUBLE(v));
ELSE
    ADDERROR(0, "cooltemp: " + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, "$.message", true)), "", " — " + PARSEJSON(r.Content, "$.message", true)));
    RETURN(NaN);
END
Write
VAR body := "{\"value\":" + Va + "}";
VAR r := SENDHTTPREQUEST("/api/thermostat/hc1/cooltemp", "POST", body, "Content-Type: application/json", "Authorization: Bearer " + AccessToken);
IF r.IsSuccess = false
    IF r.StatusCode = 401
        ADDERROR(0, "cooltemp: access token missing or wrong (EMS-ESP Settings → Security → Manage Users → key icon of an admin user)");
    ELSE
        ADDERROR(0, "cooltemp write: " + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, "$.message", true)), "", " — " + PARSEJSON(r.Content, "$.message", true)));
    END
END
Compressor Activity Multi-value Switch Read-only

Read-only status of what the compressor is doing — Off, Heating, Cooling, Hot Water, Pool, Pool Heating, Defrost or Compressor Alarm

enum numeric
Values / States: Off · Heating · Cooling · Hot Water · Pool · Pool Heating · Defrost · Compressor Alarm

Compressor Activity

Read switch state
SLEEP(60);
VAR r := SENDHTTPREQUEST("/api/boiler/hpactivity");
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST("/api/boiler/hpactivity");
END
IF r.IsSuccess
    VAR idx := PARSEJSON(r.Content, "$.index", true);
    IF ISNULL(idx)
        ADDERROR(0, "hpactivity: no value from the gateway — this controller or unit does not report it; delete this device");
        RETURN(NaN);
    END
    RETURN(TODOUBLE(idx));
ELSE
    ADDERROR(0, "hpactivity: " + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, "$.message", true)), "", " — " + PARSEJSON(r.Content, "$.message", true)));
    RETURN(NaN);
END
Compressor Running Reed Contact Read-only
boolean

Compressor Running

Read
SLEEP(60);
VAR r := SENDHTTPREQUEST("/api/boiler/hpcompon");
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST("/api/boiler/hpcompon");
END
IF r.IsSuccess
    VAR b := PARSEJSON(r.Content, "$.bool", true);
    IF ISNULL(b)
        ADDERROR(0, "hpcompon: no value from the gateway — this controller or unit does not report it; delete this device");
        RETURN(NaN);
    END
    RETURN(b);
ELSE
    ADDERROR(0, "hpcompon: " + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, "$.message", true)), "", " — " + PARSEJSON(r.Content, "$.message", true)));
    RETURN(NaN);
END
Outdoor Temperature Temperature Sensor Read-only
numeric Unit: °C

Outdoor Temperature

Read temperature
SLEEP(60);
VAR r := SENDHTTPREQUEST("/api/boiler/outdoortemp");
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST("/api/boiler/outdoortemp");
END
IF r.IsSuccess
    VAR v := PARSEJSON(r.Content, "$.value", true);
    IF ISNULL(v)
        ADDERROR(0, "outdoortemp: no value from the gateway — this controller or unit does not report it; delete this device");
        RETURN(NaN);
    END
    RETURN(TODOUBLE(v));
ELSE
    ADDERROR(0, "outdoortemp: " + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, "$.message", true)), "", " — " + PARSEJSON(r.Content, "$.message", true)));
    RETURN(NaN);
END
Flow Temperature Temperature Sensor Read-only
numeric Unit: °C

Flow Temperature

Read temperature
SLEEP(60);
VAR r := SENDHTTPREQUEST("/api/boiler/curflowtemp");
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST("/api/boiler/curflowtemp");
END
IF r.IsSuccess
    VAR v := PARSEJSON(r.Content, "$.value", true);
    IF ISNULL(v)
        ADDERROR(0, "curflowtemp: no value from the gateway — this controller or unit does not report it; delete this device");
        RETURN(NaN);
    END
    RETURN(TODOUBLE(v));
ELSE
    ADDERROR(0, "curflowtemp: " + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, "$.message", true)), "", " — " + PARSEJSON(r.Content, "$.message", true)));
    RETURN(NaN);
END
Return Temperature Temperature Sensor Read-only
numeric Unit: °C

Return Temperature

Read temperature
SLEEP(60);
VAR r := SENDHTTPREQUEST("/api/boiler/rettemp");
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST("/api/boiler/rettemp");
END
IF r.IsSuccess
    VAR v := PARSEJSON(r.Content, "$.value", true);
    IF ISNULL(v)
        ADDERROR(0, "rettemp: no value from the gateway — this controller or unit does not report it; delete this device");
        RETURN(NaN);
    END
    RETURN(TODOUBLE(v));
ELSE
    ADDERROR(0, "rettemp: " + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, "$.message", true)), "", " — " + PARSEJSON(r.Content, "$.message", true)));
    RETURN(NaN);
END
Electricity Meter Electricity Meter Read-only

Current electrical power of the compressor (kW) and total electrical energy consumption of the heat pump (kWh)

numeric Unit: W / kWh
Service Attributes
Heat delivered [kWh]Total heat energy delivered by the heat pump — thermal output, not electricity consumption

Electricity Meter

Read total consumption
IF NrgConsTotal = ""
    RETURN(NaN);
END
VAR v := PARSEJSON(NrgConsTotal, "$.value", true);
IF ISNULL(v)
    ADDERROR(1, "nrgconstotal: no value from the gateway — this controller or unit does not report it; delete this device");
    RETURN(NaN);
END
RETURN(TODOUBLE(v));
Read demand
IF HpCurrPower = ""
    RETURN(NaN);
END
VAR v := PARSEJSON(HpCurrPower, "$.value", true);
IF ISNULL(v)
    ADDERROR(0, "hpcurrpower: no value from the gateway — this controller or unit does not report it; delete this device");
    RETURN(NaN);
END
RETURN(TODOUBLE(v) / 1000);
Read (module)
SLEEP(60);
VAR r := SENDHTTPREQUEST("/api/boiler/hpcurrpower");
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST("/api/boiler/hpcurrpower");
END
IF r.IsSuccess
    HpCurrPower := r.Content;
ELSE
    HpCurrPower := "";
    ADDERROR(0, "hpcurrpower: " + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, "$.message", true)), "", " — " + PARSEJSON(r.Content, "$.message", true)));
END
SLEEP(60);
r := SENDHTTPREQUEST("/api/boiler/nrgconstotal");
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST("/api/boiler/nrgconstotal");
END
IF r.IsSuccess
    NrgConsTotal := r.Content;
ELSE
    NrgConsTotal := "";
    ADDERROR(1, "nrgconstotal: " + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, "$.message", true)), "", " — " + PARSEJSON(r.Content, "$.message", true)));
END
SLEEP(60);
r := SENDHTTPREQUEST("/api/boiler/nrgtotal");
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST("/api/boiler/nrgtotal");
END
IF r.IsSuccess
    NrgTotal := r.Content;
    IF ISNULL(PARSEJSON(NrgTotal, "$.value", true))
        ADDERROR(3, "nrgtotal: no value from the gateway — this unit does not report heat delivered; the attribute stays empty");
    END
ELSE
    NrgTotal := "";
    ADDERROR(2, "nrgtotal: " + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, "$.message", true)), "", " — " + PARSEJSON(r.Content, "$.message", true)));
END
Service Attributes
Heat delivered [kWh]
IF NrgTotal = "" RETURN(NaN); END VAR v := PARSEJSON(NrgTotal, "$.value", true); IF ISNULL(v) RETURN(NaN); END RETURN(TODOUBLE(v));
Domestic Hot Water Thermostat

Current and selected hot water temperature of the heat pump; the setpoint is sent in whole degrees and the heat pump applies its own limits

numeric Unit: °C

Domestic Hot Water

Read temperature
IF DhwCurTemp = ""
    RETURN(NaN);
END
VAR v := PARSEJSON(DhwCurTemp, "$.value", true);
IF ISNULL(v)
    ADDERROR(0, "dhw/curtemp: no value from the gateway — this controller or unit does not report it; delete this device");
    RETURN(NaN);
END
RETURN(TODOUBLE(v));
Read (module)
SLEEP(60);
VAR r := SENDHTTPREQUEST("/api/boiler/dhw/curtemp");
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST("/api/boiler/dhw/curtemp");
END
IF r.IsSuccess
    DhwCurTemp := r.Content;
ELSE
    DhwCurTemp := "";
    ADDERROR(0, "dhw/curtemp: " + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, "$.message", true)), "", " — " + PARSEJSON(r.Content, "$.message", true)));
END
SLEEP(60);
r := SENDHTTPREQUEST("/api/boiler/dhw/seltemp");
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST("/api/boiler/dhw/seltemp");
END
IF r.IsSuccess
    DhwSelTemp := r.Content;
ELSE
    DhwSelTemp := "";
    ADDERROR(1, "dhw/seltemp: " + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, "$.message", true)), "", " — " + PARSEJSON(r.Content, "$.message", true)));
END
Read desired temperature
IF DhwSelTemp = ""
    RETURN(NaN);
END
VAR v := PARSEJSON(DhwSelTemp, "$.value", true);
IF ISNULL(v)
    ADDERROR(1, "dhw/seltemp: no value from the gateway — this controller or unit does not report it; delete this device");
    RETURN(NaN);
END
RETURN(TODOUBLE(v));
Write desired temperature
VAR body := "{\"value\":" + ROUND(Se) + "}";
VAR r := SENDHTTPREQUEST("/api/boiler/dhw/seltemp", "POST", body, "Content-Type: application/json", "Authorization: Bearer " + AccessToken);
IF r.IsSuccess = false
    IF r.StatusCode = 401
        ADDERROR(0, "dhw/seltemp: access token missing or wrong (EMS-ESP Settings → Security → Manage Users → key icon of an admin user)");
    ELSE
        ADDERROR(0, "dhw/seltemp write: " + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, "$.message", true)), "", " — " + PARSEJSON(r.Content, "$.message", true)));
    END
END
Connection: Packet Parser → HTTP • Hostname: ems-esp.local
Possible improvements (15)
  • Heat pump operating mode on UI800 (thermostat top level) — UI800 reports hpoperatingmode at the thermostat top level instead of under hc1, so the template's operating mode device (and with it cooling) does not work with UI800
  • Heating circuits 2–8 — Same entities as hc1 under the hc2…hc8 path prefix; the template covers heating circuit 1 only — devices for further circuits would be copies with a different path
  • Heating circuit mode — Enum, writable: manual / auto on RC300, RC100, Rego 3000 and HMC310; off / manual / auto on BC400, UI800 and CR120
  • Heat pump cooling enabled — Boolean, writable — enables cooling on the heating circuit
  • Summer / winter switchover — winter / auto / summer, RC100 and RC300
  • Further heating circuit settings — Comfort / eco / manual setpoints, summer threshold, flow temperature limits, heating curve design temperature, offset, room influence and control mode (RC100 / RC300); the docs mark the command table as incomplete and model-dependent
  • Controller-side domestic hot water settings — DHW mode (off / on / auto), DHW set temperatures, one-time charge and circulation mode on RC100 / RC300 — the template reads and writes the heat pump (boiler) DHW entities instead
  • EMS-ESP firmware version — Already fetched by the module for the version warning; could be exposed as a module service attribute
  • Restart EMS-ESP — GET with access token; candidate for a module service action
  • Refresh all device values — Forces EMS-ESP to re-read all values from the EMS bus; no authentication
  • Temperature sensors on the gateway (DS18B20) — The kit includes a JST ZH cable for own DS18B20 sensors; their readings are available over the same REST API
  • Analog sensors and outputs of the gateway — Readings and setvalue for gateway analog inputs, counters and output pins
  • Custom entities — User-defined entities for EMS telegrams EMS-ESP does not decode yet
  • Entity discovery lists — Not a device — the live list of entities a given installation reports; the way to check which template devices will work before importing
  • Other EMS-ESP interfaces — EMS-ESP also offers Modbus TCP (since 3.7.0) and MQTT / MQTT Discovery; the template uses the REST API by entity name instead of Modbus register offsets

Sources

Found a problem with this device template?

Tell us what's wrong, what's missing, or how the template should behave. We rely on your feedback to keep the catalog accurate.

Community — unreviewed

Want to use this in your TapHome Core?

Open this template in the Customer Portal to apply it to one of your homes, or to draft a refinement and submit it back to the catalog.

Open in portal