I’m looking for the same, found anything?
No, unfort… nothing to can be seamlessly integrated. Kinda put the project on hold until I found something workable.
Hello!
Hopefully I bring good news!
you are looking for this:
I have a tesy boiler on the wall and figured all this stuff out while digging around for my daikin heatpump
(GitHub - william-sy/Daikin-BRP069A62: Creating a daikin interface other than the apps)
Now its not a integration, but it should give you a great starting point to figure some stuff out!
Made a simple POC of a tesy boiler:
sensor:
- platform: rest
resource: http://192.168.2.254/status?_=1634912123253
name: TesyBoilerWaterTemp
method: GET
value_template: "{{ value_json.gradus }}"
unit_of_measurement: "°C"
Nice!!! That is really usable
All the basic info you could want is my guess:
sensor:
- platform: time_date
display_options:
- 'time'
- 'date'
- 'date_time'
- 'date_time_utc'
- 'date_time_iso'
- 'time_date'
- 'time_utc'
- 'beat'
- platform: worldclock
name: Toronto
time_zone: America/Toronto
- platform: worldclock
name: Netherlands
time_zone: Europe/Amsterdam
- platform: worldclock
name: Kuala Lumpur
time_zone: Asia/Kuala_Lumpur
- 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
- 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
tesyboilerstate:
friendly_name: "TesyBoilerState"
value_template: "{{ state_attr('sensor.tesyboiler', 'heater_state') }}"
icon_template: mdi:help-circle
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
If you want more you can look at my repo for the URL / JSON responses.
Also if you happen to update it do share back
Pushing on/off, a new temp and boost should be possible but at some point its better to have a full integration made that also can reset kWh and change schedules
Edit reason: Updated the sensor with more info and icons
Also a template for a dashboard:
type: custom:mini-graph-card
hours_to_show: 1
points_per_hour: 15
update_interval: 30
group_by: value
name: TesyBoiler
line_width: 2
entities:
- entity: sensor.tesyboilerwatertemp
name: Water Temp
- entity: sensor.tesyboilerwatertargettemp
name: Target Temp
- entity: sensor.tesyboilerboost
show_state: true
show_graph: false
name: Boost
- entity: sensor.tesyboilerstate
show_state: true
show_graph: false
name: Boost
show:
graph: line
name: true
legend: true
icon: false
labels: true
labels_secondary: true
state_map:
- value: READY
label: Standby
- value: HEATING
label: HeatingUp
- value: '0'
label: Not boosting
- value: '0'
label: Boosting
This looks really promising! The sensors are awesome!
You captured the URL’s, but was this not HTTPS (as Tesy describes the communication highly secure between the cloud and boiler)…
What type of Tesy are you testing on? The Modeco cloud, or Bellisimo cloud?
For my scenario, switching the unit on/off, or maybe switch low/mid/high consumption/temperature, is a requirement (solar energy availability) from within HA.
Https is only needed if you are connecting to the cloud. You technically dont need to do this the local webpage does all that you want its just less pretty.
Its a Model : modeco 2
with a tesy on it, See the screen shots below
Switching the boiler on / off is not something I am immediately after at the moment as I am moving next year, So I am just experimenting with everything in this house to de-cloud myself. But happy to help script away if someone sets up a propper integration.
You can also re-flash the boiler with ESP home, as there is just a ESP in there anyway.
Also If the URLS dont work, just open up a inspector page:
Hi I tried the following for on / off / boost:
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: >
"{{ sensor.tesyboilerboost }}"
friendly_name: Boost Tesy!
icon_template: >
{% if sensor.tesyboilerboost %} mdi:rocket-launch
{% else %} mdi:rocket-launch-outline
{% 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: >
"{{ sensor.tesyboilerstate }}"
friendly_name: Tesy power switch!
icon_template: >
{% if sensor.tesyboilerstate %} mdi:toggle-switch
{% else %} mdi:toggle-switch-off
{% endif %}
But I am not happy with the state fetching seems to not really work
As you can see it assumes the state:
Ideally it just gets the state form the curl or the other sensor but no luck.
It took a bit of puzzling, but here we are its working
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 %}
What beautiful work!
Can you show me an example how to set the temperature with a command line
You could if you have not programmed a schedule (we have that so its hard without a integration)
A schedule looks like this:
&Mon00=32&Mon01=32&Mon02=32&Mon03=32&Mon04=32&Mon05=32&Mon06=50&Mon07=50&Mon08=50&Mon09=50&Mon10=50&Mon11=50&Mon12=50&Mon13=50&Mon14=50&Mon15=50&Mon16=60&Mon17=60&Mon18=40&Mon19=40&Mon20=40&Mon21=40&Mon22=30&Mon23=30
Repeat for all 7 days.
You would need to send it as plain text like this:
# P1 is week program 1
curl -X POST -H "Content-Type: text/plain" --data "this is raw data" http://192.168.2.254/setP1
But if you are in manual mode (or force it to be in manual mode):
# Set manual mode
http://192.168.2.254/modeSW?mode=1&_=1664177920325
Then you can send it with:
# Send temperature 25
http://192.168.2.254/setTemp?val=25&_=1664177655995
You can get the current value from the status one: http://192.168.2.254/status?_=1664177656195
and look at ref_gradus
( this is tesyboilerwatertargettemp
in the above ymls)
Here are all the modes:
# manual mode
http://192.168.2.254/modeSW?mode=1&_=1634912123253
# set program 1 (P1)
http://192.168.2.254/modeSW?mode=2&_=1634912027732
# set 2 Schedule 2 (P2)
http://192.168.2.254/modeSW?mode=3&_=1634912041121
# set 3 Schedule 3 (P3)
http://192.168.2.254/modeSW?mode=4&_=1634912071235
# eco 1 ( this is a Mode you cant change settings in - see the manual )
http://192.168.2.254/modeSW?mode=5&_=1634912151669
# eco 2 ( this is a Mode you cant change settings in - see the manual )
http://192.168.2.254/modeSW?mode=6&_=1634912164061
# eco 3 ( this is a Mode you cant change settings in - see the manual )
http://192.168.2.254/modeSW?mode=7&_=1634912180802
So first thing would be to get the current mode you are in:
- platform: rest
resource: http://192.168.2.254/status?_=1634912123253
name: tesyboiler
method: GET
value_template: "OK"
json_attributes:
- mode
- platform: template
sensors:
tesyboilermode:
friendly_name: "TesyBoilerMode"
value_template: "{{ state_attr('sensor.tesyboiler', 'mode') }}"
Set manual? :
switch:
- platform: command_line
switches:
tesysetmanualmode:
command_on: "/usr/bin/curl -X GET http://192.168.2.254/modeSW?mode=1&_=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
tesysetmanualtemperature:
# Some how get the temperature in here
command_on: "/usr/bin/curl -X GET http://192.168.2.254/setTemp?val=25&_=1664177655995"
command_state: "/usr/bin/curl -sX GET http://192.168.2.254/status?_=1634912123253"
# Some how this needs to evaluate to true
value_template: "{{ value_json['ref_gradus'] == }}"
friendly_name: Set Tesy manual temp
Note this is not tested, as I use the schedules
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
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.
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 , but also its has not been 3 weeks yet )
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.