EPH Controls Integration

You can track how long the boiler is actually running (different to how long a zone is on) if the boiler state is reported correctly. This is visible in the climate card where it should indicate Idle or Heating. If the thing is set to on and state is reported as Heating the boiler is on.

This currently works for systems reporting as an EMBER-PS. I am not sure if that works for EMBER-PS2 systems as they may report boiler state different.

If it works you can create helpers to track how long heating is active and so on. I use it for example to send me a warning if heating was active for more than 3h a day (some sort of attempt in cost control).

The tracking/statistics of how long the system is running and so on could be integrated within the integration or, as I have done, can be built outside the integration. Not sure what he HA standard is on doing that? Should this be part of the integration?

For me I track things like this:



1 Like

This is exactly what I want to create! Thanks you for sharing what you have done.

Yes looks like I’ve an ember-ps2 and I’m not sure it’s reporting boiler status properly, but I’ll test some more to try and confirm.

Can you explain how you did the timeline chart of idle/on etc?

Glad to see others taking advantage of this integration. I get the chart from
Devices & Integrations>Devices>EPH Controls Ember> Thermostat >Controls, then click on the icon in the upper right corner:-

Thanks, I was able to get that one, it’s the 3 horizontal bar one, that lists boiler, upstairs downstairs that I’m most interested in.

You need sensors to track boiler state.
In settings->devices->helpers you can create them

boilerdownstairs is a template with options:
{{ state_attr('climate.downstairs','hvac_action') }}

Upstairs and water are similar

boiler is a template and uses:

{% if is_state_attr('climate.hot_water', 'hvac_action', 'heating') or is_state_attr('climate.downstairs', 'hvac_action', 'heating') or is_state_attr('climate.upstairs', 'hvac_action', 'heating')  %}
            on
      {% else %}
            off
      {% endif %}

boilerdaily is a history stats helper tracking boiler and needs:
Start:

{{ today_at() if now() < today_at("23:59") else now() }}

End:

{{ now() }}

The graph to show boiler state:

  - type: history-graph
    entities:
      - entity: sensor.boilerupstairs
        name: Upstairs
      - entity: sensor.boilerdownstairs
        name: Downstairs
      - entity: sensor.boilerwater
        name: Water
      - entity: sensor.boiler
        name: Boiler

The graph to show daily usage

chart_type: bar
period: day
type: statistics-graph
entities:
  - sensor.boiler_daily
stat_types:
  - max
hide_legend: true
days_to_show: 7
title: Daily Heating
1 Like

Lovely thank you! I’ll figure it out from here now that I know it is possible.

I created a version 3.4 to add support for some more EPH variants.

I try do document for these other variants what features are working/not working here README in section ’ Supported Device Types’.

If you can report from your installation what devices you use and hat works/not works this would be helpful.

I released a version 3.5 of the EPH Controls Integration. Thanks to Jed this has support for the EMBER-TS2 family (a CP4 (COMBIPACK4) compromising of an RFRP-OT thermostat and RF1A-OT receiver and a GW04).

There should also be improved operations for the EMBER-PS2 (such as boiler state indication) as some of the data structures are shared between EMBER-TS2 and EMBER-PS2.

Turns out my old EMBER-PS is the outlier and all the other eph variants are more what one would consider the standard. This means that the underlying library pyephember2 needs some re-structuring to reflect this which may break compatibility with previous versions of this lib.

2 Likes

Only seeing this now will update and get back to you. Thanks!

This all worked perfectly thank you!!

We have been away for a few days and just back so only been able to do a little investigation on the new updates. The system was set to holiday mode on the Ember App and set to come on at 12 today. I can see from the temp chart that heating kicked in and working towards the expected target temp of 20.5 on the upper zone. This is on Mode All Day.

However the lower zone (Mode Auto), the target temperature as reported by the Ember App is 17 degrees. as it is on a setback (of 3 degrees), but in HA the control is reporting the target as 20 degrees. This jump seems to have occurred when I updated to version 3.5. I suspect the logic might for this controller has a bug.

When the heating has reached target and/or turned off I will post more insights.

This is how the Ember App is currently reporting:-

and in HA:-

I hope this helps

I added a release 3.6

  • Fix for setpoint setting for some EPH devices (maybe/hopefully fixes some issues when in AUTO mode and setting the setpoint)
  • Added per zone ‘Download Diagnostics’ to get a snapshot of pointindex data
  • Added ‘heating’ sensors per zone and overall for EPH controls to monitor actual heating runtime
1 Like

Hi, trying to set this up, Ember app is working fine, but when trying to add the Integration i get an “auth error” yet the ID & PW are correct… any ideas?

no, not had that error before reported.

  1. could you have a look in your HA logfiles to see if there is any more detail reported

  2. can you run commandline python programs? there are a few programs to test this on commandline to get more info.

** make sure that when you post anything on login debugging that you do not reveal your username/password by accident **

Hi, Looked at the logs after doing it via the UI and there was nothing, however when adding the info into the configuration.yaml i got this error on the next boot:

2026-01-08 09:44:53.306 ERROR (SyncWorker_1) [custom_components.ephember.climate] Failed to get zones

Happy to try some python, its a HA Yellow so have access to the CLI.

Download this modified pyephember2 from the mqtt branch here: pyephember2. That is the python library used by the integration and that can be used outside of HA.

In there is a test program called test.py. Run this from a shell using

python test.py --email [email protected] --password “yourpassword” -dd

This should then be more talkative in terms of errors.

However from the error message above it seems to me that the login works but later the integration fails to get zone information. What type of an EPH system do you have? Maybe it is different to the others we have encountered before.

That was very helpful! The test-py did return that it couldn’t get the zones so expect it is down to model of the controller i have…

============================================================
** Connecting to EPH Controls Ember**
============================================================
** Email: xx@xx**
** Debug Level: 0**
** HTTP Log: test_log_http**
** MQTT Log: test_log_mqtt**
** ✓ Login successful**
** ✓ HTTP logging enabled**

============================================================
** Fetching Zone Data**
============================================================
✗ Failed to fetch zones: 500 response code

I have an R47-RF with GW01.

That is the same thing I use, just 4 zones instead of 3. I would have thought that would work.

Did you get any insight from looking into the produced test_log_http file (That should contain a trace of what is communicated). (If you post any of that here, make sure no data is in there you want not to make public)

Verify the HTTP log file (test_log_http) for the full request/response. The 500 error should appear there with the server response body, which may explain why the API is failing.

This is what was in the full command with the -dd at the end (I have xx out anything personal):

============================================================
** Connecting to EPH Controls Ember**
============================================================
Email: xx@xx
Debug Level: 2
HTTP Log: test_log_http
MQTT Log: test_log_mqtt
urllib3.connectionpool: Starting new HTTPS connection (1): eu-https.topband-cloud.com:443
send: b’POST /ember-back/appLogin/login HTTP/1.1\r\nHost: eu-https.topband-cloud.com\r\nUser-Agent: python-requests/2.31.0\r\nAccept-Encoding: gzip, deflate\r\nAccept: application/json\r\nConnection: keep-alive\r\nContent-Type: application/json\r\nContent-Length: 60\r\n\r\n’
send: b’{“userName”: “xx@xx”, “password”: “xx”}’
reply: ‘HTTP/1.1 200 \r\n’
header: Date: Thu, 08 Jan 2026 11:28:33 GMT
header: Content-Type: application/json;charset=UTF-8
header: Content-Length: 173
header: Connection: keep-alive
urllib3.connectionpool: https://eu-https.topband-cloud.com:443 “POST /ember-back/appLogin/login HTTP/1.1” 200 173
✓ Login successful
✓ HTTP logging enabled
✓ Verbose HTTP console output enabled

============================================================
** Fetching Zone Data**
============================================================

============================================================
HTTP REQUEST: GET homes/list
urllib3.connectionpool: Starting new HTTPS connection (1): eu-https.topband-cloud.com:443
send: b’GET /ember-back/homes/list HTTP/1.1\r\nHost: eu-https.topband-cloud.com\r\nUser-Agent: python-requests/2.31.0\r\nAccept-Encoding: gzip, deflate\r\nAccept: application/json\r\nConnection: keep-alive\r\nAuthorization: 38487ecf9478407a8e5d0b2efd4322b2\r\nContent-Type: application/json\r\n\r\n’
reply: ‘HTTP/1.1 200 \r\n’
header: Date: Thu, 08 Jan 2026 11:28:33 GMT
header: Content-Type: application/json;charset=UTF-8
header: Content-Length: 269
header: Connection: keep-alive
urllib3.connectionpool: https://eu-https.topband-cloud.com:443 “GET /ember-back/homes/list HTTP/1.1” 200 269
HTTP RESPONSE: 200
Response Data:
{
** “data”: [**
** {**
** “deviceType”: 1,**
** “gatewayid”: “xx”,**
** “invitecode”: “xx”,**
** “name”: “xx”,**
** “productId”: null,**
** “sysTemType”: “EMBER-PS”,**
** “uid”: null,**
** “zoneCount”: 4**
** }**
** ],**
** “message”: “succ.”,**
** “status”: 0,**
** “timestamp”: 1767871713678**
}
==========================================================

**=========================================================
HTTP REQUEST: POST homesVT/zoneProgram
Request Data:
{
“gateWayId”: “xx”
}
urllib3.connectionpool: Starting new HTTPS connection (1): eu-https.topband-cloud.com:443
send: b’POST /ember-back/homesVT/zoneProgram HTTP/1.1\r\nHost: eu-https.topband-cloud.com\r\nUser-Agent: python-requests/2.31.0\r\nAccept-Encoding: gzip, deflate\r\nAccept: application/json\r\nConnection: keep-alive\r\nAuthorization: 38487ecf9478407a8e5d0b2efd4322b2\r\nContent-Type: application/json\r\nContent-Length: 27\r\n\r\n’
send: b’{“gateWayId”: “xx”}’
reply: ‘HTTP/1.1 500 \r\n’
header: Date: Thu, 08 Jan 2026 11:28:33 GMT
header: Content-Type: application/json;charset=UTF-8
header: Content-Length: 98
header: Connection: keep-alive
urllib3.connectionpool: https://eu-https.topband-cloud.com:443 “POST /ember-back/homesVT/zoneProgram HTTP/1.1” 500 98
✗ Failed to fetch zones: 500 response code

It gets my home correct but fails at the Zones… They are configured and can see in the App.

Your system responds with a deviceType 1. My one here is a deviceType 3 and others I have seen were a 4. So, I assume you have an install that is there for way more than 5 years?

So when zone information is requested pyephember2 uses the endpoint /zoneProgram and it seems for your system the EPH cloud does not provide that.

Options

  • Find workaround with existing known queries to see if the information can be obtained
  • Find out what your mobile app is using to puzzle the information together (obviously a different sequence of http requests).
  • Update the GW01 (maybe thats possible)