Hi All
Thank you for everyone that shared their experience on this. I have re-used a bunch of learnings from this post and others and completed an integration from my Geyserwise Max to Home Assistant. This should also be possible with the Delta and TSE models but I have not tested that.
Sorry for the lack of media in the post, as a new user I seem to be limited to only one media file per post.
Steps I followed:
- Replace Geyserwise Max panel board(3 temp digit model, 2 digit model is not compatible) with the IOT/Tuya panel board.
- I have standardised on Tasmota for firmware so flashed ESP 12F with latest Tasmota firmware and replaced Tuya WBR3 chip.
- Configure Tasmota with option Tuya MCU (54) and MQTT back to Home Assistant.
- Including my sensor file and lovelace configuration for Homeassistant below.
Step 1 & 2: Follow the steps as described by @kidcolt here
Step 3: Ensure you configure the Tasmota module type as Tuya MCU(54), this configures the ESP to interface with the tuya MCU module via the UART.
In order to periodically send the Tuya messages recieved on the UART but avoid unneccessary cyclic messages set the following options in the console settings.
SetOption66 1
SetOption137 1
Step 4: Add new sensor configuration for the Geyser. Here is my geyser1.yaml file. Make sure you correct the mqtt topic to reflect your settings in Tasmota.
I still need to map the correct error code values to human readable descriptions for the geyser1_error_code sensor. If anyone know the correct values for each error type please let me know.
# Requires:
# Transplant WBR3 chip transplanted with ESP-12F
# Tasmota configured for device type TuyaMCU (54)
# SetOption66 1 in tasmota
# To avoid some cyclic MCU <-> ESP messages enable SetOption137 1
# "DpType1Id1": 0, Element Control
# "DpType4Id2": 1, Mode (holiday/normal)
# "DpType2Id10": 47, Geyser Temperature
# "DpType4Id13": 0, Element Status
# "DpType5Id20": "0x0000", Error Code
# "DpType4Id101": 0, Pump Status
# "DpType2Id102": 7, Geyser Solar Diff Temp
# "DpType2Id103": 55, Geyser block 1 - Max Temp
# "DpType2Id104": 55, Geyser block 2 - Max Temp
# "DpType2Id105": 55, Geyser block 3 - Max Temp
# "DpType2Id106": 55, Geyser block 4 - Max Temp
# "DpType2Id107": 5, Geyser Antifreeze Temp
# "DpType2Id108": 21, Geyser Collector Temp
# "DpType2Id109": 2 Element Runtime hours
# TuyaSend<x> dpId,data
# x=1 Send Boolean(Type 1)
# x=2 Send Integer(Type 2) or 4 byte
# x=3 Send ASCII(Type 3) String
# x=4 Send Enum(Type 4) data
# x=5 Send HEX String(Type 3) data, does not require 0x prefix
mqtt:
sensor:
- name: "Temp"
object_id: "geyser1_temp"
state_topic: "tele/tasmota_geyser1/RESULT"
device_class: temperature
value_template: >-
{% if value_json['TuyaReceived']['DpType2Id10'] is defined %}
{{ value_json['TuyaReceived']['DpType2Id10'] | int }}
{% endif %}
unit_of_measurement: "°C"
- name: "Collector Temp"
object_id: geyser1_collector_temp
icon: mdi:solar-power-variant
state_topic: "tele/tasmota_geyser1/RESULT"
device_class: temperature
value_template: >-
{% if value_json['TuyaReceived']['DpType2Id108'] is defined %}
{{ value_json['TuyaReceived']['DpType2Id108'] | int }}
{% endif %}
unit_of_measurement: "°C"
- name: "Antifreeze Temp"
object_id: geyser1_antifreeze_temp
state_topic: "tele/tasmota_geyser1/RESULT"
device_class: temperature
value_template: >-
{% if value_json['TuyaReceived']['DpType2Id107'] is defined %}
{{ value_json['TuyaReceived']['DpType2Id107'] | int }}
{% endif %}
unit_of_measurement: "°C"
- name: "Element Runtime"
object_id: geyser1_element_runtime
state_topic: "tele/tasmota_geyser1/RESULT"
device_class: duration
state_class: measurement
value_template: >-
{% if value_json['TuyaReceived']['DpType2Id109'] is defined %}
{{ value_json['TuyaReceived']['DpType2Id109'] | int }}
{% endif %}
unit_of_measurement: "hrs"
- name: "Block 1 - Max Temp"
object_id: geyser1_block1_temp
state_topic: "tele/tasmota_geyser1/RESULT"
device_class: temperature
value_template: >-
{% if value_json['TuyaReceived']['DpType2Id103'] is defined %}
{{ value_json['TuyaReceived']['DpType2Id103'] | int }}
{% endif %}
unit_of_measurement: "°C"
- name: "Block 2 - Max Temp"
object_id: geyser1_block2_temp
state_topic: "tele/tasmota_geyser1/RESULT"
device_class: temperature
value_template: >-
{% if value_json['TuyaReceived']['DpType2Id104'] is defined %}
{{ value_json['TuyaReceived']['DpType2Id104'] | int }}
{% endif %}
unit_of_measurement: "°C"
- name: "Block 3 - Max Temp"
object_id: geyser1_block3_temp
state_topic: "tele/tasmota_geyser1/RESULT"
device_class: temperature
value_template: >-
{% if value_json['TuyaReceived']['DpType2Id105'] is defined %}
{{ value_json['TuyaReceived']['DpType2Id105'] | int }}
{% endif %}
unit_of_measurement: "°C"
- name: "Block 4 - Max Temp"
object_id: geyser1_block4_temp
state_topic: "tele/tasmota_geyser1/RESULT"
device_class: temperature
value_template: >-
{% if value_json['TuyaReceived']['DpType2Id106'] is defined %}
{{ value_json['TuyaReceived']['DpType2Id106'] | int }}
{% endif %}
unit_of_measurement: "°C"
- name: "Solar Diff Temp"
object_id: geyser1_solar_diff_temp
state_topic: "tele/tasmota_geyser1/RESULT"
device_class: temperature
value_template: >-
{% if value_json['TuyaReceived']['DpType2Id102'] is defined %}
{{ value_json['TuyaReceived']['DpType2Id102'] | int }}
{% endif %}
unit_of_measurement: "°C"
- name: "Error Code"
object_id: geyser1_error_code
state_topic: "tele/tasmota_geyser1/RESULT"
icon: mdi:information-box-outline
value_template: >-
{% if value_json['TuyaReceived']['DpType5Id20'] is defined %}
{% if (value_json['TuyaReceived']['DpType5Id20'] | string) == '0x0000' %}
[00] Normal
{%elif (value_json['TuyaReceived']['DpType5Id20'] | string) == '0x00E1' %}
[E1] Earth Leakage
{%elif (value_json['TuyaReceived']['DpType5Id20'] | string) == '0x00E2' %}
[E2] Dry Burn Protection
{%elif (value_json['TuyaReceived']['DpType5Id20'] | string) == '0x00E3' %}
[E3] Sensor failure water geyser
{%elif (value_json['TuyaReceived']['DpType5Id20'] | string) == '0x00E4' %}
[E4] Heating Loss
{%elif (value_json['TuyaReceived']['DpType5Id20'] | string) == '0x00E5' %}
[E5] Over temperature protection
{%elif (value_json['TuyaReceived']['DpType5Id20'] | string) == '0x00E6' %}
[E6] Water Leak
{%elif (value_json['TuyaReceived']['DpType5Id20'] | string) == '0x00E7' %}
[E7] Communication failue
{%elif (value_json['TuyaReceived']['DpType5Id20'] | string) == '0x00E8' %}
[E8] Collector temperature probe
{%elif (value_json['TuyaReceived']['DpType5Id20'] | string) == '0x00E9' %}
[E9] Pump failure
{%else%}
Unknown
{% endif %}
{% endif %}
- name: "Element"
object_id: geyser1_element
state_topic: "tele/tasmota_geyser1/RESULT"
icon: mdi:fire
value_template: >-
{% if value_json['TuyaReceived']['DpType4Id13'] is defined %}
{% if (value_json['TuyaReceived']['DpType4Id13'] | string) == '0' %}
OFF
{%elif (value_json['TuyaReceived']['DpType4Id13'] | string) == '1' %}
ON
{%else%}
Unknown
{% endif %}
{% else %}
Unknown
{% endif %}
- name: "Pump"
object_id: geyser1_pump
state_topic: "tele/tasmota_geyser1/RESULT"
icon: mdi:pipe-valve
value_template: >-
{% if value_json['TuyaReceived']['DpType4Id101'] is defined %}
{% if (value_json['TuyaReceived']['DpType4Id101'] | string) == '0' %}
OFF
{%elif (value_json['TuyaReceived']['DpType4Id101'] | string) == '1' %}
ON
{%else%}
Unknown
{% endif %}
{% else %}
Unknown
{% endif %}
binary_sensor:
- name: "Status"
object_id: geyser1_status
state_topic: "tele/tasmota_geyser1/RESULT"
icon: mdi:alert
device_class: problem
value_template: >-
{% if value_json['TuyaReceived']['DpType5Id20'] is defined %}
{% if value_json['TuyaReceived']['DpType5Id20'] == '0x0000' %}
OFF
{% else %}
ON
{% endif %}
{% else %}
OFF
{% endif %}
switch:
- name: "Power"
object_id: geyser1_power
state_topic: "tele/tasmota_geyser1/RESULT"
icon: mdi:power
state_on: 1
state_off: 0
value_template: >-
{% if value_json['TuyaReceived'].DpType1Id1 is defined %}
{{ value_json.TuyaReceived.DpType1Id1 }}
{% else %}
0
{% endif %}
command_topic: "cmnd/tasmota_geyser1/TuyaSend1"
payload_on: "1, 1"
payload_off: "1, 0"
availability_topic: "tele/tasmota_geyser1/LWT"
payload_available: "Online"
payload_not_available: "Offline"
- name: "Holiday Mode"
object_id: geyser1_holiday_mode
state_topic: "tele/tasmota_geyser1/RESULT"
icon: mdi:umbrella-beach
state_on: 0
state_off: 1
value_template: >-
{% if value_json['TuyaReceived'].DpType4Id2 is defined %}
{{ value_json.TuyaReceived.DpType4Id2 }}
{% else %}
1
{% endif %}
command_topic: "cmnd/tasmota_geyser1/TuyaSend4"
payload_on: "2, 0"
payload_off: "2, 1"
availability_topic: "tele/tasmota_geyser1/LWT"
payload_available: "Online"
payload_not_available: "Offline"
sensor:
- platform: history_stats
name: Geyser1 Element Runtime
entity_id: sensor.geyser1_element
state: "ON"
type: time
start: "{{ now().replace(hour=0, minute=0, second=0, microsecond=0) }}"
duration:
days: 1
- platform: template
sensors:
geyser1_element_runtime_rounded:
friendly_name: Element Runtime
icon_template: mdi:progress-clock
value_template: >
{{ (timedelta(hours=states('sensor.geyser1_element_runtime_2') | float(0)) | string)[:-3] }}
This is what my geyser lovelace configuration looks like. I use the custom Mushroom and apexcharts-card Frontend extensions installed from HACS.
Here is the yaml for that display.
type: vertical-stack
cards:
- type: custom:mushroom-title-card
title: Geyser 1
alignment: center
- type: horizontal-stack
cards:
- type: custom:mushroom-entity-card
entity: switch.geyser1_power
layout: horizontal
icon_color: red
tap_action:
action: toggle
- type: custom:mushroom-entity-card
entity: switch.geyser1_holiday_mode
layout: horizontal
icon_color: green
tap_action:
action: toggle
- show_name: true
show_icon: true
show_state: true
type: glance
entities:
- entity: sensor.geyser1_collector_temp
- entity: sensor.geyser1_temp
- entity: sensor.geyser1_element_runtime_rounded
state_color: false
columns: 3
- type: horizontal-stack
cards:
- type: custom:mushroom-entity-card
layout: vertical
entity: sensor.geyser1_pump
- type: custom:mushroom-entity-card
layout: vertical
entity: sensor.geyser1_element
icon_color: red
- type: tile
entity: binary_sensor.geyser1_status
color: orange
vertical: true
show_entity_picture: false
- type: custom:apexcharts-card
apex_config:
chart:
height: 140%
yaxis:
- id: first
decimals: 0
apex_config:
tickAmount: 4
- id: second
opposite: true
decimals: 0
apex_config:
tickAmount: 1
graph_span: 10h
header:
show: false
show_states: true
colorize_states: true
series:
- entity: sensor.geyser1_temp
yaxis_id: first
stroke_width: 2
- entity: sensor.geyser1_collector_temp
yaxis_id: first
stroke_width: 2
- entity: sensor.geyser1_element
type: column
name: Element State
group_by:
func: avg
duration: 1min
stroke_width: 1
transform: 'return x === ''ON'' ? 1 : 0;'
yaxis_id: second
- type: history-graph
entities:
- entity: sensor.geyser1_error_code
This allows monitoring the temperatures, status of various components and control the element through home assistant.
I quite like the graph which shows the blue collector temp vs the orange geyser temperature. The red indicates the element runtime overlayed onto the temperature.
Enjoy!