Geyserwise WIFI module integration (Request)

Good Morning,

I have just received an API key from Geyserwise - I have the Geyserwise Client Integration API Document.

I will send the Document to whoever is willing to help.

Kindly give me some guidance on the integration.

Regards

Hi, Iā€™m very new to HA, and have opted for localTuya, which is working. Iā€™m battling however to get all the entities youā€™ve shown here. Also donā€™t have DSP 10 for current temperature. Have used Sensor, not sure if I should use climate.

Hi @HomeGeorge, please ignore my previous post on temperature. I got it working. I do however have a question around the enity type for DSP10. You used sensor, and it works well. I want to however use CLIMATE, because that will allow for an HVAC type control on a mushroom-climate card, which works pretty well too. Sensor entity type will unfortunately not cut it,

Any advice?

Will also be nice, to know what you used in your sample dashboard.

Interested in your approach.

Iā€™m assuming you have not done anything to the device (just the Tuya enabled Geyserwise board).

I am keen to create MQTT - Tuya link in the Homie standard to automatically populate devices discovered on Tuya to MQTT. I see itā€™s a little supported Home Assistant but the Homie standard is supported by OpenHab. In OpenHAB these devices are then autodiscovered based on Homie standard.

Iā€™m using OpenHAB so not going to switch anytime soon.

I also want to summarise the approaches to solve this problem found on this thread:

  1. Involves the Geyserwise WiFi module and their API. I donā€™t think this is sold anymore?
  2. Geyserwise Tuya Boards which are sold and an easy upgrade to an existing Geyserwise Max or otherwie (e.g. @viv-01 's approach)
    a) This device could be paired with the cloud and used as is using cloud connection.
    b) This could also use a local tuya connection.
    c) A combination of the above.
  3. Geyserwise Tuya board but with a chip replacement and firmware for that chip (developed by @Jack_Kitley in this thread.

Are these all the solutions?

My questions relates to 2 (a-c). Does that allow access to the full range of variables (14 it seems to be for the Max product). @the_brains seems to have solved this? Does this apply to the Tuya solution? Is this cloud?

Tuya cloud only gives you access to some of the sensor data. Tuya local gives you access to everything @the_brains listed above.

Does this apply to cloud? Or to the local?

Just got my Geyserwise Max Tuya. I see what you mean under the Tuya Project panel. Here it lists the additional variables withe the DP Instruction mode:

Cloud and Local

1 Like

Once set, youā€™ll be able to see all the attributes, I went the route of using Tuya local. You can run local and cloud simultaneously

1 Like

No reason to go through Geyserwise to be honest. Just use Tuya.

Got it all connected up just now. Will share scripts later as it may be helpful for multiple Tuya devices. Though not HA specific. Graph shows panel temperature and geyser temperature below.

Hi @HomeGeorge been looking for a ā€œsimpleā€ solution to replace existing solar/electric geyser combo, which will integrate to HA, but still run independently if HA down.
If Iā€™m understanding correctly your solution entails:

  1. Buy Geyserwise Max Tuya WiFi controller kit.
  2. Use HA Tuya-Local integration to read/write to all points locally using HA.
  3. Retain Tuya Cloud for non-HA users/access.
  4. No replacing chips, flashing boards, writing scripts etc.

If this is case Iā€™m going shopping.

Look fwd to hearing from you.

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:

  1. Replace Geyserwise Max panel board(3 temp digit model, 2 digit model is not compatible) with the IOT/Tuya panel board.
  2. I have standardised on Tasmota for firmware so flashed ESP 12F with latest Tasmota firmware and replaced Tuya WBR3 chip.
  3. Configure Tasmota with option Tuya MCU (54) and MQTT back to Home Assistant.
  4. 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!

1 Like
I have the error outputs for the TSE model 
(0 = No Fault) ("Earth_leakge", "Dry_burn", "Wt_sensor_fault", "Heating_loss", "Over_temp", "Water_leak", "Comm_failure", "Ct_probe_fault", "Pump_failure")		

hopefully that will help you. 

Could you possibly uide me on how to get the "geyser1.yaml" file loaded not sure if you jsut pasted this into your Configuration.yaml, or if you keep it as a seperate file? 

thanks


Hi @Gaza84

I make use of the packages directive in the configuration.yaml file, have a look at this Packages - Home Assistant

Essentially I include all packages (.yaml files) placed in the folder called packages.

These are then loaded because I have the following in my configuration.yaml file.

homeassistant:
  packages: !include_dir_named packages

I have found loading using studio code server extension makes it easy to create and edit these files.

thanks for the guidance! every day is a learning oppertunity, this helped me tidy up a few things.

Hi Andrew, sorry for this very late reply - I wish HA forum would send me an email for posts aimed at me.
I ended up using a ESP8266 for the job.