Home assistant supported inverters

Yes, I am using the ESP32. The 8266 Runs out of memory.
My system settings

I am not much of a UI builder so I have built my dashboards from bits and pieces I found all over. Busy documenting and adding them to source control so that other people new to the scene can re-use them… They will also be part of my bootstap that will be free for anyone to copy and change them. The learning curve for newbies to HA is quite steep

I installed an inverter about a year ago, and then discovered that the power gets wasted once the battery is full so I needed a way to store the energy as hot water. I installed home assistant and have since become convinced we are on a path towards smart homes and a smart grid.

Personally I’m a fan of a wired solution when it goes to anything more critical than Sonoff switches. I list some alternatives&reasons here

Will be happy to link to your repo if the intention is to help the community

It looks good so far! The reason why I only allow editing after clicking on them is that it just becomes too easy to change settings by whoever has access to HA!

Can still probably take this one step further by “Locking” the option to write settings to the inverter.

The images I posted above was the standard setup under the device (Settings->Devices&Service->Devices)

I guess a lot depends on what you consider “helping the community”.

My aim is to help people connect their inverter to an automation system (Home Assistant) so that they can focus on making their home smart and using the excess power effectively to lower their bills. I want to give them a plug and play solar monitoring system that can be expanded to automate things in the future.

Lots of people buy Solar assistant, but you need a Rasp PI (or Orange PI these days) and they kinda force you to buy another pieces of kit. Then you still need to buy a cable to connect it to the PI. I would much rather prefer people use any old computer like an old laptop/computer and give it a purpose (running home assistant) than throwing it on the landfill or being forced to buy more kit

You are forced to buy some cable to interface with the inverter, so my reasoning is that it might as well be a ESP32 with the correct cable to plug into the inverter that contains all the logic decode the inverter “language” so you can focus on understanding how to optimise your power usage.

For now I am not open sourcing the firmware that goes onto the ESP32 module, I might change my mind about this in the future, but I can just imagine getting all kinds of queries where people soldered their own version and it does not want to work expecting my code to be the silver bullet.
Electronics is a bit of a minefield, I bought several different micro controllers and wiring them up I realised that: what works on one gives loads of CRC errors on a different one. Some have poor power regulators which leads to all kinds of funny issues. Some have pullup/pull down resistors on certain pins. Sometimes you simply cannot get hold of a certain controller or version, sometimes you get a “copy/fake”.
GPIO is not general purpose … well mostly it is is but…
Fine soldering is not everyone’s idea of fun, and debugging with a multi-meter is quite something else.

So I am not sure if I fit your definition of helping the community being closed source. I have been on the receiving end of strong opinions of open source advocates. I would be interested on hearing your opinion on the subject of open sourcing the code and I welcome any other input other people may have.

Ultimately I am trying to start my own business and in the process make the world a greener place

Indeed, but they do provide extensive dashboards and support. I demoed it in 2021 and the main reason I decided against it was the (then) lack of support for HASS & the energy management in HASS. This was also my feedback to Pierre back then, together with working addon code for HASS.

In the end you will buy something. Ranging from R36 to R3000. In most cases you will need to invest some of your time to really get it working perfectly (perfectly is also subjective)

You can still help the community irrespective of open/closed source.

The nice thing of open source is when you have people working together to improve something. My original need was the HASS energy dashboard and I did system mode writes with fixed profiles. Others added flexible write sensors, documentation (automation examples for the Spanish market), multiple options for adaptors (ranging from R36 for a simple adaptor to R800 for a complete gateway). Single & three phase support. And hopefully soon multiple Inverter support.

What the open source community cannot provide is support, since this does not scale and here commercial models makes sense. I still recommend people with many questions/emailing me directly to get Solar-Assistant if they want a supported product. Your ESP product could very well be one of these I recommend.

The tinkerers can still play with ESPHome based options. Although that might involve some electronic knowledge and be a bit clunky for writes today. At least the writes will not always stay this way and I believe the team will add support for modbus write sensors in the future.

1 Like

HI, I love you dashboard. I was trying to get the same look. I’m already running sloar-assistant connected to be DEYE 8KW inverter but I’m battling to get what you have.
when do you think you will be able to share or publish your code?
I have this below which is the one thats created automatically which is cool but I really like yours.

Technically not my code, bits and pieces I found on the internet, happy to share and help people

Ok let me just paste something to get you started
I was hoping to release the first version but then life happened and I will be offline for another 10 days due to a hiking trip.

You need a couple of frontend HACS plugins too

plugins needed:
slider-entity-row
layout-card

The easiest would be:
three dots… Edit Dashboard, then add a new empty tab… then three dots… use the Raw configuration editor, scroll down and locate where the yaml is for that tab… and paste the contents below into that tab (copied straight from the raw yaml)
Save…
Then you need to change all the entities to match whatever your system uses

  - theme: Backend-selected
    title: Time of Use
    type: custom:grid-layout
    layout:
      grid-template-columns: 1fr 1fr 1fr 1fr
      grid-template-rows: auto
      grid-template-areas: |
        ". header header ."
        ". system priority ."
        ". prog1 prog2 ."
        ". prog3 prog4 ."
        ". prog5 prog6 ."
      mediaquery:
        '(max-width: 800px)':
          grid-template-columns: auto
          grid-template-areas: |
            "header"
            "system"
            "priority"
            "prog1"
            "prog2"
            "prog3"
            "prog4"
            "prog5"
            "prog6"
    badges: []
    cards:
      - type: entities
        entities:
          - entity: switch.deyeinverter_time_of_use
        show_header_toggle: false
        view_layout:
          grid-area: system
      - type: vertical-stack
        cards:
          - type: custom:mushroom-template-card
            primary: Program 1
            secondary: >-
              {{ states("input_datetime.timezone1_time") }} - {{
              states("input_datetime.timezone2_time") }}
            icon: mdi:timer
            multiline_secondary: false
            badge_icon: mdi:lightning-bolt
            icon_color: blue
            badge_color: green
            fill_container: false
          - type: horizontal-stack
            cards:
              - type: entities
                entities:
                  - entity: input_datetime.timezone1_time
              - type: entities
                entities:
                  - entity: input_datetime.timezone2_time
          - type: entities
            entities:
              - entity: number.deyeinverter_timezone1_power
                name: Power
                grow: true
              - entity: number.deyeinverter_timezone1_soc
                name: Battery SOC
              - entity: number.deyeinverter_timezone1_voltage
                name: Battery Voltage
              - entity: select.deyeinverter_timezone1_charge
                name: Charge option
        view_layout:
          grid-area: prog1
      - type: vertical-stack
        cards:
          - type: custom:mushroom-template-card
            primary: Program 2
            secondary: >-
              {{ states("input_datetime.timezone2_time") }} - {{
              states("input_datetime.timezone3_time") }}
            icon: mdi:timer
            multiline_secondary: false
            badge_icon: mdi:lightning-bolt
            icon_color: blue
            badge_color: green
            fill_container: false
          - type: horizontal-stack
            cards:
              - type: entities
                entities:
                  - entity: input_datetime.timezone2_time
              - type: entities
                entities:
                  - entity: input_datetime.timezone3_time
          - type: entities
            entities:
              - entity: number.deyeinverter_timezone2_power
                name: Power
                grow: true
              - entity: number.deyeinverter_timezone2_soc
                name: Battery SOC
              - entity: number.deyeinverter_timezone2_voltage
                name: Battery Voltage
              - entity: select.deyeinverter_timezone2_charge
                name: Charge from
        view_layout:
          grid-area: prog2
      - type: vertical-stack
        cards:
          - type: custom:mushroom-template-card
            primary: Program 3
            secondary: >-
              {{ states("input_datetime.timezone3_time") }} - {{
              states("input_datetime.timezone4_time") }}
            icon: mdi:timer
            multiline_secondary: false
            badge_icon: mdi:lightning-bolt
            icon_color: blue
            badge_color: green
            fill_container: false
          - type: horizontal-stack
            cards:
              - type: entities
                entities:
                  - entity: input_datetime.timezone3_time
              - type: entities
                entities:
                  - entity: input_datetime.timezone4_time
          - type: entities
            entities:
              - entity: number.deyeinverter_timezone3_power
                name: Power
                grow: true
              - entity: number.deyeinverter_timezone3_soc
                name: Battery SOC
              - entity: number.deyeinverter_timezone3_voltage
                name: Battery Voltage
              - entity: select.deyeinverter_timezone3_charge
                name: Charge Options
        view_layout:
          grid-area: prog3
      - type: vertical-stack
        cards:
          - type: custom:mushroom-template-card
            primary: Program 4
            secondary: >-
              {{ states("input_datetime.timezone4_time") }} - {{
              states("input_datetime.timezone5_time") }}
            icon: mdi:timer
            multiline_secondary: false
            badge_icon: mdi:lightning-bolt
            icon_color: blue
            badge_color: green
            fill_container: false
          - type: horizontal-stack
            cards:
              - type: entities
                entities:
                  - entity: input_datetime.timezone4_time
              - type: entities
                entities:
                  - entity: input_datetime.timezone5_time
          - type: entities
            entities:
              - entity: number.deyeinverter_timezone4_power
                name: Power
                grow: true
              - entity: number.deyeinverter_timezone4_soc
                name: Battery SOC
              - entity: number.deyeinverter_timezone4_voltage
                name: Battery Voltage
              - entity: select.deyeinverter_timezone4_charge
                name: Charge Options
        view_layout:
          grid-area: prog4
      - type: vertical-stack
        cards:
          - type: custom:mushroom-template-card
            primary: Program 5
            secondary: >-
              {{ states("input_datetime.timezone5_time") }} - {{
              states("input_datetime.timezone6_time") }}
            icon: mdi:timer
            multiline_secondary: false
            badge_icon: mdi:lightning-bolt
            icon_color: blue
            badge_color: green
            fill_container: false
          - type: horizontal-stack
            cards:
              - type: entities
                entities:
                  - entity: input_datetime.timezone5_time
              - type: entities
                entities:
                  - entity: input_datetime.timezone6_time
          - type: entities
            entities:
              - entity: number.deyeinverter_timezone5_power
                name: Power
                grow: true
              - entity: number.deyeinverter_timezone5_soc
                name: Battery SOC
              - entity: number.deyeinverter_timezone5_voltage
                name: Battery Voltage
              - entity: select.deyeinverter_timezone5_charge
                name: Charge Options
        view_layout:
          grid-area: prog5
      - type: vertical-stack
        cards:
          - type: custom:mushroom-template-card
            primary: Program 6
            secondary: >-
              {{ states("input_datetime.timezone6_time") }} - {{
              states("input_datetime.timezone1_time") }}
            icon: mdi:timer
            multiline_secondary: false
            badge_icon: mdi:lightning-bolt
            icon_color: blue
            badge_color: green
            fill_container: false
          - type: horizontal-stack
            cards:
              - type: entities
                entities:
                  - entity: input_datetime.timezone6_time
              - type: entities
                entities:
                  - entity: input_datetime.timezone1_time
          - type: entities
            entities:
              - entity: number.deyeinverter_timezone6_power
                name: Power
                grow: true
              - entity: number.deyeinverter_timezone6_soc
                name: Battery SOC
              - entity: number.deyeinverter_timezone6_voltage
                name: Battery Voltage
              - entity: select.deyeinverter_timezone6_charge
                name: Charge Options
        view_layout:
          grid-area: prog6
      - type: custom:mushroom-title-card
        title: Inverter Settings
        alignment: center
        view_layout:
          grid-area: header
      - type: entities
        entities:
          - entity: select.deyeinverter_energy_management_model
        view_layout:
          grid-area: priority

thanks so much that really helped me. I just need to rename the entities but at least i have the shell now. It’s the furtherest i’ve managed to get. It seems as if solar-assistant MQTT HA integration differs somewhat and complicates the entity names that it exposes. for example on the Deye “time of Use” is called “Use timer” in Solar-assistant. They aren’t the same as on the inverter. I also can’t find the time slot options that are normally under time of use. That could just be me being dof. I still have a lot to play around with and see if i can figure it out.
I also find the development on Solar-Assistant slow and the exposing of new features etc is lacking and doesn’t really assist with load-shedding integration etc etc. Not discounting what he has done and I really appreciate it.

I just realised that I defined “home assistant time entities” for these in the configuration.yaml as the datetime objects need to be translated back and forth to the inverter format and home assistant format (done with automations)

The dongle I built (to be sold in limited quantities starting June) allows all the setting to be updated, not sure if everything is writable over Solar Assistant MQTT (assuming solar assistant needs to both publish and listed for messages to make this happen)

your configuration.yaml (to define the entities that you will edit via the screen and store a time value)

input_datetime:
  timezone1_time:
    name: Timezone 1 Time
    has_date: false
    has_time: true
  timezone2_time:
    name: Timezone 2 Time
    has_date: false
    has_time: true
  timezone3_time:
    name: Timezone 3 Time
    has_date: false
    has_time: true
  timezone4_time:
    name: Timezone 4 Time
    has_date: false
    has_time: true
  timezone5_time:
    name: Timezone 5 Time
    has_date: false
    has_time: true
  timezone6_time:
    name: Timezone 6 Time
    has_date: false
    has_time: true

Automations: (that will copy the values from the inverter to dateTime objects( in home assistant), and when the user edits the time, it will convert the time to the format the inverter expects and update the inverter values

alias: InverterConfig send update to inverter
description: ""
trigger:
  - platform: state
    entity_id:
      - input_datetime.timezone1_time
      - input_datetime.timezone2_time
      - input_datetime.timezone3_time
      - input_datetime.timezone4_time
      - input_datetime.timezone5_time
      - input_datetime.timezone6_time
condition:
  - condition: template
    value_template: "{{ trigger.to_state.state != 'unavailable' }}"
action:
  - service: number.set_value
    target:
      entity_id: number.deyeinverter_timezone1_time
    data:
      value: >-
        {{state_attr('input_datetime.timezone1_time', 'timestamp') |
        timestamp_custom("%H%M", false) | float}}
  - service: number.set_value
    target:
      entity_id: number.deyeinverter_timezone2_time
    data:
      value: >-
        {{state_attr('input_datetime.timezone2_time', 'timestamp') |
        timestamp_custom("%H%M", false) | float}}
  - service: number.set_value
    target:
      entity_id: number.deyeinverter_timezone3_time
    data:
      value: >-
        {{state_attr('input_datetime.timezone3_time', 'timestamp') |
        timestamp_custom("%H%M", false) | float}}
  - service: number.set_value
    target:
      entity_id: number.deyeinverter_timezone4_time
    data:
      value: >-
        {{state_attr('input_datetime.timezone4_time', 'timestamp') |
        timestamp_custom("%H%M", false) | float}}
  - service: number.set_value
    target:
      entity_id: number.deyeinverter_timezone5_time
    data:
      value: >-
        {{state_attr('input_datetime.timezone5_time', 'timestamp') |
        timestamp_custom("%H%M", false) | float}}
  - service: number.set_value
    target:
      entity_id: number.deyeinverter_timezone6_time
    data:
      value: >-
        {{state_attr('input_datetime.timezone6_time', 'timestamp') |
        timestamp_custom("%H%M", false) | float}}
mode: single

alias: InverterConfig send values to  HA time objects
description: ""
trigger:
  - platform: state
    entity_id:
      - number.deyeinverter_timezone1_time
      - number.deyeinverter_timezone2_time
      - number.deyeinverter_timezone3_time
      - number.deyeinverter_timezone4_time
      - number.deyeinverter_timezone5_time
      - number.deyeinverter_timezone6_time
condition:
  - condition: template
    value_template: "{{ trigger.to_state.state != 'unavailable' }}"
action:
  - service: input_datetime.set_datetime
    target:
      entity_id: input_datetime.timezone1_time
    data:
      time: >-
        {% set min = ((states('number.deyeinverter_timezone1_time') | int) %
        100) %} {% set hour = ((states('number.deyeinverter_timezone1_time') |
        int) // 100) %} {{hour|format('02d')}}:{{min|format('02d')}}:00
  - service: input_datetime.set_datetime
    target:
      entity_id: input_datetime.timezone2_time
    data:
      time: >-
        {% set min = ((states('number.deyeinverter_timezone2_time') | int) %
        100) %} {% set hour = ((states('number.deyeinverter_timezone2_time') |
        int) // 100) %} {{hour|format('02d')}}:{{min|format('02d')}}:00
  - service: input_datetime.set_datetime
    target:
      entity_id: input_datetime.timezone3_time
    data:
      time: >-
        {% set min = ((states('number.deyeinverter_timezone3_time') | int) %
        100) %} {% set hour = ((states('number.deyeinverter_timezone3_time') |
        int) // 100) %} {{hour|format('02d')}}:{{min|format('02d')}}:00
  - service: input_datetime.set_datetime
    target:
      entity_id: input_datetime.timezone4_time
    data:
      time: >-
        {% set min = ((states('number.deyeinverter_timezone4_time') | int) %
        100) %} {% set hour = ((states('number.deyeinverter_timezone4_time') |
        int) // 100) %} {{hour|format('02d')}}:{{min|format('02d')}}:00
  - service: input_datetime.set_datetime
    target:
      entity_id: input_datetime.timezone5_time
    data:
      time: >-
        {% set min = ((states('number.deyeinverter_timezone5_time') | int) %
        100) %} {% set hour = ((states('number.deyeinverter_timezone5_time') |
        int) // 100) %} {{hour|format('02d')}}:{{min|format('02d')}}:00
  - service: input_datetime.set_datetime
    target:
      entity_id: input_datetime.timezone6_time
    data:
      time: >-
        {% set min = ((states('number.deyeinverter_timezone6_time') | int) %
        100) %} {% set hour = ((states('number.deyeinverter_timezone6_time') |
        int) // 100) %} {{hour|format('02d')}}:{{min|format('02d')}}:00
mode: single

A preview of what I have so far

1 Like

thanks, the time values worked.
currently looking like this, I jut need to update the entities

The solar desktop is here

Please note that this is still rough around the edges as I rushed to get something committed to git. I will be offline for about 10-14 days depending on the availability of signal

Anyone got something working that allows updates to a Deye inverter using the Solarman WiFi logger?