New electric water heater / boiler (integrated with HA)

Here is a Full config yml:


rest_command:
  tsmt:
    url: "http://192.168.2.254/setTemp?val={{ temperature }}&_=1664177655995"
    method: GET

automation:
  - alias: "Tesy Temperature input automatically changed"
    trigger:
      platform: state
      entity_id: sensor.tesyboilertargettemp
    action:
      service: input_number.set_value
      target:
        entity_id: input_number.tesyboilermanualtempinput
      data:
        value: "{{ trigger.to_state.state }}"
  - alias: "Tesy Temperature input manually changed"
    trigger:
      platform: state
      entity_id: input_number.tesyboilermanualtempinput
    action:
      service: rest_command.tsmt
      data:
        temperature: "{{ trigger.to_state.state }}"

input_number:
  tesyboilermanualtempinput:
    name: Set Tesy Manual Temp
    min: 14
    max: 75
    step: 1
    unit_of_measurement: "°C"
    icon: mdi:temperature-celsius

switch:
  - platform: command_line
    switches:
      tesyboostonoff:
        command_on: "/usr/bin/curl -X GET http://192.168.2.254/boostSW?mode=1&_=1634911445424"
        command_off: "/usr/bin/curl -X GET http://192.168.2.254/boostSW?mode=0&_=1634911446795"
        command_state: "/usr/bin/curl -sX GET http://192.168.2.254/status?_=1634912123253"
        value_template: "{{ value_json['boost'] == '1' }}"
        friendly_name: Boost Tesy!
        icon_template: >
          {% if value_json['boost'] == '0' %} mdi:rocket
          {% elif value_json['boost'] == '1' %} mdi:rocket-launch
          {% else %} mdi:help-circle
          {% endif %}
      tesyonoff:
        command_on: "/usr/bin/curl -X GET http://192.168.2.254/power?val=on&_=1664015398260"
        command_off: "/usr/bin/curl -X GET http://192.168.2.254/power?val=off&_=1664015398260"
        command_state: "/usr/bin/curl -sX GET http://192.168.2.254/status?_=1634912123253"
        value_template: "{{ value_json['power_sw'] == 'on' }}"
        friendly_name: Tesy power switch!
        icon_template: >
          {% if value_json['power_sw'] == "on" %} mdi:toggle-switch
          {% else %} mdi:toggle-switch-off
          {% endif %}
      tesyresetpower:
        command_on: "/usr/bin/curl -X GET http://192.168.2.254/resetPow?_=1634912213060"
        friendly_name: Tesy power Reset!
      tesysetsetmanualmode:
        command_on: "/usr/bin/curl -X GET http://192.168.2.254/modeSW?mode=1&_=1664177920325"
        # Set a default schedule here if you dont want manual mode any longer
        command_off: "/usr/bin/curl -X GET http://192.168.2.254/modeSW?mode=2&_=1664177920325"
        command_state: "/usr/bin/curl -sX GET http://192.168.2.254/status?_=1634912123253"
        value_template: "{{ value_json['mode'] == '1' }}"
        friendly_name: Set Tesy manual mode
        icon_template: >
          {% if value_json['mode'] == '1' %} mdi:water-boiler
          {% elif  value_json['mode'] == '2' %} mdi:calendar
          {% elif  value_json['mode'] == '3' %} mdi:calendar
          {% elif  value_json['mode'] == '4' %} mdi:calendar
          {% elif  value_json['mode'] == '5' %} mdi:sprout
          {% elif  value_json['mode'] == '6' %} mdi:sprout
          {% elif  value_json['mode'] == '7' %} mdi:sprout
          {% else %} mdi:help-circle
          {% endif %}

sensor:
  - platform: rest
    resource: http://192.168.2.254/status?_=1634912123253
    name: tesyboiler
    method: GET
    value_template: "OK"
    json_attributes:
      - gradus
      - ref_gradus
      - heater_state
      - err_flag
      - boost
      - power_sw
      - volume
      - watts
      - mode
  - platform: rest
    resource: http://192.168.2.254/calcRes?_=1634912123253
    name: tesyboilerpower
    method: GET
    value_template: "OK"
    json_attributes:
      - kwh
      - ltc
      - resetDate
  - platform: template
    sensors:
      tesyboilerwatertemp:
        friendly_name: "TesyBoilerWaterTemp"
        value_template: "{{ state_attr('sensor.tesyboiler', 'gradus') }}"
        unit_of_measurement: "°C"
        icon_template: mdi:temperature-celsius
      tesyboilerwatertargettemp:
        friendly_name: "TesyBoilerWaterTargetTemp"
        value_template: "{{ state_attr('sensor.tesyboiler', 'ref_gradus') }}"
        unit_of_measurement: "°C"
        icon_template: mdi:temperature-celsius
      tesyboilertargettemp:
        friendly_name: "TesyBoilerTargetTemp"
        value_template: "{{ state_attr('sensor.tesyboiler', 'ref_gradus') }}"
      tesyboilerstate:
        friendly_name: "TesyBoilerState"
        value_template: "{{ state_attr('sensor.tesyboiler', 'heater_state') }}"
        icon_template: mdi:help-circle
      tesyboilermode:
        friendly_name: "TesyBoilerMode"
        value_template: "{{ state_attr('sensor.tesyboiler', 'mode') }}"
        icon_template: mdi:calendar
      tesyboilerwatts:
        friendly_name: "TesyBoilerWatts"
        value_template: "{{ state_attr('sensor.tesyboiler', 'watts') }}"
        unit_of_measurement: "W"
        icon_template: mdi:power-plug
      tesyboilerwatervolume:
        friendly_name: "TesyBoilerWaterVolume"
        value_template: "{{ state_attr('sensor.tesyboiler', 'volume') }}"
        unit_of_measurement: "L"
        icon_template: mdi:cup-water
      tesyboileronoff:
        friendly_name: "TesyBoilerOnOff"
        value_template: "{{ state_attr('sensor.tesyboiler', 'power_sw') }}"
        icon_template: mdi:help-circle
      tesyboilerboost:
        friendly_name: "TesyBoilerBoost"
        value_template: "{{ state_attr('sensor.tesyboiler', 'boost') }}"
        icon_template: mdi:arrow-up-circle
      tesyboilererror:
        friendly_name: "TesyBoilerError"
        value_template: "{{ state_attr('sensor.tesyboiler', 'err_flag') }}"
        icon_template: mdi:water-boiler-alert
      tesyboilerkwhalltime:
        friendly_name: "TesyBoilerKwhAllTime"
        value_template: "{{ state_attr('sensor.tesyboilerpower', 'ltc') }}"
        unit_of_measurement: "kWh"
        icon_template: mdi:lightning-bolt
      tesyboilerkwhafterreset:
        friendly_name: "TesyBoilerKwhAfterReset"
        value_template: "{{ state_attr('sensor.tesyboilerpower', 'kwh') }}"
        unit_of_measurement: "kWh"
        icon_template: mdi:lightning-bolt
      tesyboilerkwhresetdate:
        friendly_name: "TesyBoilerKwhResetDate"
        value_template: "{{ state_attr('sensor.tesyboilerpower', 'resetDate') }}"
        icon_template: mdi:calendar-blank-outline

Things that could be implemented more:

  • Rest comands:
    – Set a different mode (1 to 7)
    – Reset kWh usage (good for adding it to the energy dashboard?)
  • Full display with edit:
    – Change a actual schedule (better to have a proper implementation)

Hope it helps, From here everything should be easy enough for the next person. Ill stop posting more config :wink:

1 Like

Thank you for your extensive example.
It works great! now I can heat my water through solar panels.
If the temperature is too low, the gas boiler takes over.

1 Like

Thanks! That is greath! Can you share your cards config?

Really great stuff. I will have a look at how an integration should look like, and what is needed for it.

As I have no boiler/heater yet, it will be difficult to test. I will have a first look at simulating a boiler. Maybe I can find the Tesy firmware, and put it in an ESP device have a stub test device.

Hi Jos,what type Tesy boiler/heater do you own? Is it the same one (Modeco cloud)?

Hi William,

Great, I did not find out how to send commands towards the boiler.
Thanks a lot!

Is there a specific reason that you chose to use an automation for rest?
I found out that the boiler didn’t like a lot of frequent rest commands (I used to have each attribute in a seperate entity). Had to turn it off every 2 to 3 weeks because it became unresponsive.

I use this currently:

  - platform: rest
    name: boiler
    resource: http://boiler/status
    json_attributes:
      - gradus
      - ref_gradus
      - heater_state
      - boost
      - power_sw
    value_template: "{{ value_json.boiler }}"
    scan_interval: 60
  - platform: template
    sensors:
      gradus:
        friendly_name: "Huidige temperatuur"
        value_template: "{{ state_attr('sensor.boiler', 'gradus') }}"
        device_class: temperature
        unit_of_measurement: "°C"
      ref_gradus:
        friendly_name: "Ingestelde temperatuur"
        value_template: "{{ state_attr('sensor.boiler', 'ref_gradus') }}"
        device_class: temperature
        unit_of_measurement: "°C"
      heater_state:
        friendly_name: "Verwarm status"
        value_template: "{{ state_attr('sensor.boiler', 'heater_state') }}"
      boost:
        friendly_name: "Boost status"
        value_template: "{{ state_attr('sensor.boiler', 'boost') }}"
      power_sw:
        friendly_name: "Apparaat status"
        value_template: "{{ state_attr('sensor.boiler', 'power_sw') }}"

  - platform: rest
    name: boiler_power
    resource: http://boiler/calcRes
    value_template: '{{ value_json.sum | title }}'
    scan_interval: 60

  - platform: template
    sensors:
      boiler_power_usage:
        friendly_name: "Totaal stroomverbruik boiler"
        unit_of_measurement: 'kWh'
        device_class: power
        icon_template: mdi:power-plug
        value_template: "{{ ((states('sensor.boiler_power') | float / 3600000) * 2400) | round(2) }}"

And to get it on the energy dashboard, I use an utility meter

utility_meter: 
  daily_energy:
    name: boiler_energy-daily
    source: sensor.boiler_power_usage
    cycle: daily
    net_consumption: false

Regarding the power calculation, I think you have a newer (firmware) version.
My boiler has a weird calculation of power usage, hence the calculation in the template
It is formatted like this (output from /calcRes)

{"sum":"1695972","resetDate":"2022-01-01 02:43:41","volume":"100","watt":"2400"}

My latest yaml can be found here:

I use rest because it is what the app and the webinterface are using if you go to the local IP, And it spams the boiler if you look at the traffic!
So unless you send the wrong command I have not been able to make the boiler upset.
(been there :wink: , but also its has not been 3 weeks yet :stuck_out_tongue: )

Perhaps you should post a screen shot or 2 for the power usage on the boilers website! (power/version)
A JSON output of calcRes would also be of interest

Did anyone find a download page for the boiler firmwares? I am unable sofar and send a request for this via their website, but no answer yet.

Hey fellas, first off GREAT work William! I see that a lot of people are happy with it.

I do have some issues with the rest requests however.

Initially I tried with the simplest command to just gather the heater’s status just like the first comment you wrote, what I got as response was the following :

Error parsing value: 'value_json' is undefined (value: <html><meta http-equiv="refresh" content="0; URL='/'" /><body>File Not Found</body></html>, template: {{ value_json['gradus'] == '1' }})

Then I tried with the entire config.yaml from GIT again with no luck.
All the requests were failing with “File Not Found”
Just to add that I’ve changed the IP to match my water heater one.
The Heater itself is Tesy Belissimo

Anyone else has similar issue and did you manage to find a working solution?

@belastingvormulier, so nice to see this is getting the attention it so desperately needs!!! Also really good to see that more people show interest! Thanks for all your effort already.
@ronnie_j, can’t wait to see an integration coming to life!!!

Now, I just should buy a Tessy boiler asap :upside_down_face:

Please open the boiler in your browser and inspect element f12? and see the traffic that is floating from your browser to the boiler.

It might need different requests as the modeco one.

As for the firmware I highly doubt it you will get your hands on it, but one brave soul should/could extract it from the boiler itsefl

Its a pricy item to buy

But it is available

Better buy the right one :wink:
It seems to be very model specific so far :frowning:

1 Like

Sorry, I misread, you are using the automation for inputting the temperature into an entity :slight_smile:
It was already late last night (facepalm)

I’ve been using rest for a year or 2 now too, based on my findings from GitHub - gummiboll/tesytalk: cli tool/library to talk to tesy water heaters

So seeing that you discovered the other commands really pleased me.
I wasn’t able to find it, how did you do it? Because I’m not able to control it through its own web interface.
When I started using it, I had 1 rest command per attribute, so it really flooded the boiler with requests… Thats why I’m now also using the scan_interval: 60

I also do not need the &_=16xxxxxxxx id’s to get it working by the way.

You can see the output of /calcRes in my previous post, that’s the complete output, also noted it below again.
As you see it has different attributes than you use in yours, hence the calculation I had to do to get it in to proper kWh.

{"sum":"1695972","resetDate":"2022-01-01 02:43:41","volume":"100","watt":"2400"}

And the screenshot of the energy dashboard, including the daily power usage

Thanks for the suggestion. This will probably lead me to the solution, because opening the boiler IP in the browser shows only a textfield with “IoT” in it. Currently I’ve been controlling the boiler with the TesyCloud app, which probably blocked the local connection with the boiler.
Will try to revert to factory setting and start over to see what will happen.

1 Like

Hi Valeri,

What happens if you go to http:// ip of boiler /status?

Thanks for the suggestion.
It removes the /status part like a redirect
And the result page is this, a blank page with “IoT” as text :smiley:

Ohh and yes, I tried with https (Which doesn’t make sense, but still)

And you do have the Modeco smart/cloud boiler with tesy app?
If you just visit the IP-address of the boiler do you see anything similar like this?

Hah weird, tesyCloud app, which in theory is the official app in Bulgaria for Tesy does not really provide you with any information. The only thing you can do in Settings is Logout…
Apart from that, the app has some sort of Local Boiler Control, which is stuck on Loading (Yes I am connected on my local Lan) I Even tried it on browser from PC connected with LAN to the router.

Did you download this MODECO from Google Play or from a third-party?

Perhaps you have an older firmware or maybe a slightly different product than we have.
William’s web interface also looks different from mine.

On the web interface of the boiler itself I can only specify Timezone, Wifi, Volume, see the FW version (FW15.2N@M) and specify my MyTesy account.

I can’t control it through it’s own web interface.
But my boiler firmware version, does have some pages reporting JSON through for example http:// boiler IP /status.
And with the URL’s / pages William discovered, I am able to ‘control it’ locally.

Control (for me) of the boiler goes through the mobile app or web, found here:
tesyCloud (mytesy.com)