[TUTORIAL] SolarMax S-Series inverter integration

Hello,

I would like to share with you my tutorial on how to integrate SolarMax inverters into Home Assistant. I will only focus on the S-Series inverters (2000S / 3000S / 4200S / 6000S) since those are the ones I use myself.


Prologue

In order to communicate with the SolarMax S-Series inverters you should (but don’t have to) understand how the custom MaxComm protocol works on these inverters.
Below you can find the latest (as of writing this post) official English protocol description obtained from the SolarMax customer support. Sadly I can not provide a direct link to the English version as the website seems to be under construction. If you kindly ask their support they should send you the file via email. However the German protocol description seems to be more up to date anyway.


:warning: Important Information :warning:

:warning: Please read this file first before proceeding! :warning:
20230829_MaxComm_Protocol_Explanation.txt

Also take a look at the official protocol description.
MaxComm_Protokollbeschreibung_DE.pdf
MaxComm_Protocol_Description_EN.pdf → mailto:[email protected]

:warning: Please note that if the insolation on the solar panels is not high enough the SolarMax inverters put themselves in a “sleep mode” where the ethernet port will not be able to communicate. So don’t panic if the connection to your inverter is not working. :warning:


:warning: :warning: :warning: :warning: :warning: :warning:
Again before proceeding please read my “MaxComm_Protocol_Explanation.txt”.
It quickly explains the most important aspects of the involved protocol, how to create your own payload to query only the data you want/need and more importantly how to change the device address in the payload.
:warning: :warning: :warning: :warning: :warning: :warning:


Part 1 - SolarMax inverter configuration

Go into the settings menu of your SolarMax inverter and change the following settings.

  1. Device Address = 001
  2. Ethernet = On
  3. IP = according to your home network
  4. Netmask = according to your home network
  5. Connect the RJ45/RS485 port to your home network.
(optional) - Multiple SolarMax inverters configuration

If you have multiple inverters you can connect them all to your home network with only one ethernet cable by daisy chaining them together using their RJ45/RS485 and RS485 ports.

  1. Configure 1st inverter like explained above.
  2. Configure the 2nd inverter.
    2.1. Device Address = 002
    2.2. Ethernet = Off
  3. In case you have even more inverters configure them like the 2nd inverter and increment the device address so each inverter has a unique device address. The IP and Netmask settings can be left untouched.
  4. Connect the RJ45/RS485 port of the 1st inverter to you home network.
  5. Connect the RS485 port of your 1st inverter to the RJ45/RS485 port of your 2nd inverter.
  6. Connect the RS485 port of your 2nd inverter to the RJ45/RS485 port of your 3rd inverter.
  7. And so on…

Part 2 - Home Assistant integration

Integrating the SolarMax inverters into Home Assistant will make your configuration.yaml quite confusing to read since it adds a lot of yaml code. Therefore I moved all manually created sensors/templates from the configuration.yaml in subfolders called “sensors” and “templates” containing the individual yaml files.
You can read more about it here: https://www.home-assistant.io/docs/configuration/splitting_configuration/

You can of course also directly add the sensor and templates to your configuration.yaml but I will not support this here since I think it is a very messy thing to do.

  1. Create the folders “sensors” and “templates” in the same folder where your configuration.yaml is stored.
  2. In the “sensors” folder create a file called sensor_solarmax_inverters.yaml and add the following code to it.
    :warning: Verify that the host and port matches the settings of your inverter(s).
    :warning: Make sure to remove the additional sensor for the 2nd inverter if you don’t need it.
# SolarMax 6000S
- platform: tcp
  scan_interval: 10
  name: "SolarMax 6000S"
  host: 192.168.0.101
  port: 12345
  payload: "{FB;01;82|64:UDC;IDC;UL1;IL1;PAC;PRL;TNF;KDY;KLD;KMT;KLM;KYR;KLY;KT0;TKK;SYS;KHR;CAC;TYP;SWV;BDN;ADR;PIN;DDY;DMT;DYR;TMI;THR|2285}"

# EVERYTHING BELOW HERE IS ONLY NEEDED IF YOU HAVE MULTIPLE INVERTERS
# EVERYTHING BELOW HERE IS ONLY NEEDED IF YOU HAVE MULTIPLE INVERTERS
# EVERYTHING BELOW HERE IS ONLY NEEDED IF YOU HAVE MULTIPLE INVERTERS

# SolarMax 2000S
- platform: tcp
  scan_interval: 10
  name: "SolarMax 2000S"
  host: 192.168.0.101
  port: 12345
  payload: "{FB;02;82|64:UDC;IDC;UL1;IL1;PAC;PRL;TNF;KDY;KLD;KMT;KLM;KYR;KLY;KT0;TKK;SYS;KHR;CAC;TYP;SWV;BDN;ADR;PIN;DDY;DMT;DYR;TMI;THR|2286}"
  1. In the “templates” folder create a file called template_solarmax_inverters.yaml and add the following code to it.
    :warning: Make sure to remove the additional template for the 2nd inverter and the combined template if you don’t need it.
# SolarMax 6000S template
- sensor:
    - name: "SolarMax 6000S 00 DC Voltage"
      device_class: voltage
      unit_of_measurement: "V"
      state_class: measurement
      state: "{{ states('sensor.solarmax_6000s').split(';')[2] | regex_findall_index('=([0-9A-F]+)') | int(base=16) * 0.1 }}"

- sensor:
    - name: "SolarMax 6000S 01 DC Current"
      device_class: current
      unit_of_measurement: "A"
      state_class: measurement
      state: "{{ states('sensor.solarmax_6000s').split(';')[3] | regex_findall_index('=([0-9A-F]+)') | int(base=16) * 0.01 }}"

- sensor:
    - name: "SolarMax 6000S 02 AC Voltage"
      device_class: voltage
      unit_of_measurement: "V"
      state_class: measurement
      state: "{{ states('sensor.solarmax_6000s').split(';')[4] | regex_findall_index('=([0-9A-F]+)') | int(base=16) * 0.1 }}"

- sensor:
    - name: "SolarMax 6000S 03 AC Current"
      device_class: current
      unit_of_measurement: "A"
      state_class: measurement
      state: "{{ states('sensor.solarmax_6000s').split(';')[5] | regex_findall_index('=([0-9A-F]+)') | int(base=16) * 0.01 }}"

- sensor:
    - name: "SolarMax 6000S 04 AC Output"
      device_class: power
      unit_of_measurement: "W"
      state_class: measurement
      state: "{{ states('sensor.solarmax_6000s').split(';')[6] | regex_findall_index('=([0-9A-F]+)') | int(base=16) * 0.5 }}"

- sensor:
    - name: "SolarMax 6000S 05 AC Output (relative)"
      device_class: power_factor
      unit_of_measurement: "%"
      state_class: measurement
      state: "{{ states('sensor.solarmax_6000s').split(';')[7] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 6000S 06 AC Frequency"
      device_class: frequency
      unit_of_measurement: "Hz"
      state_class: measurement
      state: "{{ states('sensor.solarmax_6000s').split(';')[8] | regex_findall_index('=([0-9A-F]+)') | int(base=16) * 0.01 }}"

- sensor:
    - name: "SolarMax 6000S 07 Energy (today)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total_increasing
      state: "{{ states('sensor.solarmax_6000s').split(';')[9] | regex_findall_index('=([0-9A-F]+)') | int(base=16) * 0.1 }}"

- sensor:
    - name: "SolarMax 6000S 08 Energy (yesterday)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total
      state: "{{ states('sensor.solarmax_6000s').split(';')[10] | regex_findall_index('=([0-9A-F]+)') | int(base=16) * 0.1 }}"

- sensor:
    - name: "SolarMax 6000S 09 Energy (this month)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total_increasing
      state: "{{ states('sensor.solarmax_6000s').split(';')[11] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 6000S 10 Energy (last month)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total
      state: "{{ states('sensor.solarmax_6000s').split(';')[12] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 6000S 11 Energy (this year)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total_increasing
      state: "{{ states('sensor.solarmax_6000s').split(';')[13] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 6000S 12 Energy (last year)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total
      state: "{{ states('sensor.solarmax_6000s').split(';')[14] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 6000S 13 Energy (total)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total_increasing
      state: "{{ states('sensor.solarmax_6000s').split(';')[15] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 6000S 14 Temperature (inverter)"
      device_class: temperature
      unit_of_measurement: "°C"
      state_class: measurement
      state: "{{ states('sensor.solarmax_6000s').split(';')[16] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 6000S 15 Operating Mode"
      state_class: measurement
      state: "{{ states('sensor.solarmax_6000s').split(';')[17] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 6000S 16 Operating Hours"
      device_class: duration
      unit_of_measurement: "h"
      state_class: total
      state: "{{ states('sensor.solarmax_6000s').split(';')[18] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 6000S 17 Start-ups"
      state_class: total
      state: "{{ states('sensor.solarmax_6000s').split(';')[19] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 6000S 18 Type"
      state_class: measurement
      state: "{{ states('sensor.solarmax_6000s').split(';')[20] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 6000S 19 Software Version"
      state_class: measurement
      state: "{{ states('sensor.solarmax_6000s').split(';')[21] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 6000S 20 Build Number"
      state_class: measurement
      state: "{{ states('sensor.solarmax_6000s').split(';')[22] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 6000S 21 Network Address"
      state_class: measurement
      state: "{{ states('sensor.solarmax_6000s').split(';')[23] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 6000S 22 Capacity (installed)"
      device_class: power
      unit_of_measurement: "W"
      state_class: measurement
      state: "{{ states('sensor.solarmax_6000s').split(';')[24] | regex_findall_index('=([0-9A-F]+)') | int(base=16) * 0.5 }}"

- sensor:
    - name: "SolarMax 6000S 23 Date (day)"
      state_class: measurement
      state: "{{ states('sensor.solarmax_6000s').split(';')[25] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 6000S 24 Date (month)"
      state_class: measurement
      state: "{{ states('sensor.solarmax_6000s').split(';')[26] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 6000S 25 Date (year)"
      state_class: measurement
      state: "{{ '20' ~ states('sensor.solarmax_6000s').split(';')[27] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 6000S 26 Time (minute)"
      state_class: measurement
      state: "{{ states('sensor.solarmax_6000s').split(';')[28] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 6000S 27 Time (hour)"
      state_class: measurement
      state: "{{ states('sensor.solarmax_6000s').split(';')[29] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

# EVERYTHING BELOW HERE IS ONLY NEEDED IF YOU HAVE MULTIPLE INVERTERS
# EVERYTHING BELOW HERE IS ONLY NEEDED IF YOU HAVE MULTIPLE INVERTERS
# EVERYTHING BELOW HERE IS ONLY NEEDED IF YOU HAVE MULTIPLE INVERTERS

# SolarMax 2000S template
- sensor:
    - name: "SolarMax 2000S 00 DC Voltage"
      device_class: voltage
      unit_of_measurement: "V"
      state_class: measurement
      state: "{{ states('sensor.solarmax_2000s').split(';')[2] | regex_findall_index('=([0-9A-F]+)') | int(base=16) * 0.1 }}"

- sensor:
    - name: "SolarMax 2000S 01 DC Current"
      device_class: current
      unit_of_measurement: "A"
      state_class: measurement
      state: "{{ states('sensor.solarmax_2000s').split(';')[3] | regex_findall_index('=([0-9A-F]+)') | int(base=16) * 0.01 }}"

- sensor:
    - name: "SolarMax 2000S 02 AC Voltage"
      device_class: voltage
      unit_of_measurement: "V"
      state_class: measurement
      state: "{{ states('sensor.solarmax_2000s').split(';')[4] | regex_findall_index('=([0-9A-F]+)') | int(base=16) * 0.1 }}"

- sensor:
    - name: "SolarMax 2000S 03 AC Current"
      device_class: current
      unit_of_measurement: "A"
      state_class: measurement
      state: "{{ states('sensor.solarmax_2000s').split(';')[5] | regex_findall_index('=([0-9A-F]+)') | int(base=16) * 0.01 }}"

- sensor:
    - name: "SolarMax 2000S 04 AC Output"
      device_class: power
      unit_of_measurement: "W"
      state_class: measurement
      state: "{{ states('sensor.solarmax_2000s').split(';')[6] | regex_findall_index('=([0-9A-F]+)') | int(base=16) * 0.5 }}"

- sensor:
    - name: "SolarMax 2000S 05 AC Output (relative)"
      device_class: power_factor
      unit_of_measurement: "%"
      state_class: measurement
      state: "{{ states('sensor.solarmax_2000s').split(';')[7] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 2000S 06 AC Frequency"
      device_class: frequency
      unit_of_measurement: "Hz"
      state_class: measurement
      state: "{{ states('sensor.solarmax_2000s').split(';')[8] | regex_findall_index('=([0-9A-F]+)') | int(base=16) * 0.01 }}"

- sensor:
    - name: "SolarMax 2000S 07 Energy (today)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total_increasing
      state: "{{ states('sensor.solarmax_2000s').split(';')[9] | regex_findall_index('=([0-9A-F]+)') | int(base=16) * 0.1 }}"

- sensor:
    - name: "SolarMax 2000S 08 Energy (yesterday)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total
      state: "{{ states('sensor.solarmax_2000s').split(';')[10] | regex_findall_index('=([0-9A-F]+)') | int(base=16) * 0.1 }}"

- sensor:
    - name: "SolarMax 2000S 09 Energy (this month)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total_increasing
      state: "{{ states('sensor.solarmax_2000s').split(';')[11] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 2000S 10 Energy (last month)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total
      state: "{{ states('sensor.solarmax_2000s').split(';')[12] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 2000S 11 Energy (this year)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total_increasing
      state: "{{ states('sensor.solarmax_2000s').split(';')[13] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 2000S 12 Energy (last year)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total
      state: "{{ states('sensor.solarmax_2000s').split(';')[14] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 2000S 13 Energy (total)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total_increasing
      state: "{{ states('sensor.solarmax_2000s').split(';')[15] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 2000S 14 Temperature (inverter)"
      device_class: temperature
      unit_of_measurement: "°C"
      state_class: measurement
      state: "{{ states('sensor.solarmax_2000s').split(';')[16] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 2000S 15 Operating Mode"
      state_class: measurement
      state: "{{ states('sensor.solarmax_2000s').split(';')[17] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 2000S 16 Operating Hours"
      device_class: duration
      unit_of_measurement: "h"
      state_class: total
      state: "{{ states('sensor.solarmax_2000s').split(';')[18] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 2000S 17 Start-ups"
      state_class: total
      state: "{{ states('sensor.solarmax_2000s').split(';')[19] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 2000S 18 Type"
      state_class: measurement
      state: "{{ states('sensor.solarmax_2000s').split(';')[20] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 2000S 19 Software Version"
      state_class: measurement
      state: "{{ states('sensor.solarmax_2000s').split(';')[21] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 2000S 20 Build Number"
      state_class: measurement
      state: "{{ states('sensor.solarmax_2000s').split(';')[22] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 2000S 21 Network Address"
      state_class: measurement
      state: "{{ states('sensor.solarmax_2000s').split(';')[23] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 2000S 22 Capacity (installed)"
      device_class: power
      unit_of_measurement: "W"
      state_class: measurement
      state: "{{ states('sensor.solarmax_2000s').split(';')[24] | regex_findall_index('=([0-9A-F]+)') | int(base=16) * 0.5 }}"

- sensor:
    - name: "SolarMax 2000S 23 Date (day)"
      state_class: measurement
      state: "{{ states('sensor.solarmax_2000s').split(';')[25] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 2000S 24 Date (month)"
      state_class: measurement
      state: "{{ states('sensor.solarmax_2000s').split(';')[26] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 2000S 25 Date (year)"
      state_class: measurement
      state: "{{ '20' ~ states('sensor.solarmax_2000s').split(';')[27] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 2000S 26 Time (minute)"
      state_class: measurement
      state: "{{ states('sensor.solarmax_2000s').split(';')[28] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

- sensor:
    - name: "SolarMax 2000S 27 Time (hour)"
      state_class: measurement
      state: "{{ states('sensor.solarmax_2000s').split(';')[29] | regex_findall_index('=([0-9A-F]+)') | int(base=16) }}"

# SolarMax Combined template
- sensor:
    - name: "SolarMax Combined 00 AC Output"
      device_class: power
      unit_of_measurement: "W"
      state_class: measurement
      state: "{{ states('sensor.solarmax_2000s_04_ac_output') | float + states('sensor.solarmax_6000s_04_ac_output') | float }}"
      availability: >
        {% set solarmax_2000s_04_ac_output = states('sensor.solarmax_2000s_04_ac_output') | float(default=0) %}
        {% set solarmax_6000s_04_ac_output = states('sensor.solarmax_6000s_04_ac_output') | float(default=0) %}
        {{ solarmax_2000s_04_ac_output > 0 or solarmax_6000s_04_ac_output > 0 }}

- sensor:
    - name: "SolarMax Combined 01 Energy (today)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total_increasing
      state: "{{ states('sensor.solarmax_2000s_07_energy_today') | float + states('sensor.solarmax_6000s_07_energy_today') | float }}"
      availability: >
        {% set solarmax_2000s_04_ac_output = states('sensor.solarmax_2000s_04_ac_output') | float(default=0) %}
        {% set solarmax_6000s_04_ac_output = states('sensor.solarmax_6000s_04_ac_output') | float(default=0) %}
        {{ solarmax_2000s_04_ac_output > 0 or solarmax_6000s_04_ac_output > 0 }}

- sensor:
    - name: "SolarMax Combined 02 Energy (yesterday)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total
      state: "{{ states('sensor.solarmax_2000s_08_energy_yesterday') | float + states('sensor.solarmax_6000s_08_energy_yesterday') | float }}"
      availability: >
        {% set solarmax_2000s_04_ac_output = states('sensor.solarmax_2000s_04_ac_output') | float(default=0) %}
        {% set solarmax_6000s_04_ac_output = states('sensor.solarmax_6000s_04_ac_output') | float(default=0) %}
        {{ solarmax_2000s_04_ac_output > 0 or solarmax_6000s_04_ac_output > 0 }}

- sensor:
    - name: "SolarMax Combined 03 Energy (this month)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total_increasing
      state: "{{ states('sensor.solarmax_2000s_09_energy_this_month') | float + states('sensor.solarmax_6000s_09_energy_this_month') | float }}"
      availability: >
        {% set solarmax_2000s_04_ac_output = states('sensor.solarmax_2000s_04_ac_output') | float(default=0) %}
        {% set solarmax_6000s_04_ac_output = states('sensor.solarmax_6000s_04_ac_output') | float(default=0) %}
        {{ solarmax_2000s_04_ac_output > 0 or solarmax_6000s_04_ac_output > 0 }}

- sensor:
    - name: "SolarMax Combined 04 Energy (last month)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total
      state: "{{ states('sensor.solarmax_2000s_10_energy_last_month') | float + states('sensor.solarmax_6000s_10_energy_last_month') | float }}"
      availability: >
        {% set solarmax_2000s_04_ac_output = states('sensor.solarmax_2000s_04_ac_output') | float(default=0) %}
        {% set solarmax_6000s_04_ac_output = states('sensor.solarmax_6000s_04_ac_output') | float(default=0) %}
        {{ solarmax_2000s_04_ac_output > 0 or solarmax_6000s_04_ac_output > 0 }}

- sensor:
    - name: "SolarMax Combined 05 Energy (this year)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total_increasing
      state: "{{ states('sensor.solarmax_2000s_11_energy_this_year') | float + states('sensor.solarmax_6000s_11_energy_this_year') | float }}"
      availability: >
        {% set solarmax_2000s_04_ac_output = states('sensor.solarmax_2000s_04_ac_output') | float(default=0) %}
        {% set solarmax_6000s_04_ac_output = states('sensor.solarmax_6000s_04_ac_output') | float(default=0) %}
        {{ solarmax_2000s_04_ac_output > 0 or solarmax_6000s_04_ac_output > 0 }}

- sensor:
    - name: "SolarMax Combined 06 Energy (last year)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total
      state: "{{ states('sensor.solarmax_2000s_12_energy_last_year') | float + states('sensor.solarmax_6000s_12_energy_last_year') | float }}"
      availability: >
        {% set solarmax_2000s_04_ac_output = states('sensor.solarmax_2000s_04_ac_output') | float(default=0) %}
        {% set solarmax_6000s_04_ac_output = states('sensor.solarmax_6000s_04_ac_output') | float(default=0) %}
        {{ solarmax_2000s_04_ac_output > 0 or solarmax_6000s_04_ac_output > 0 }}

- sensor:
    - name: "SolarMax Combined 07 Energy (total)"
      device_class: energy
      unit_of_measurement: "kWh"
      state_class: total_increasing
      state: "{{ states('sensor.solarmax_2000s_13_energy_total') | float + states('sensor.solarmax_6000s_13_energy_total') | float }}"
      availability: >
        {% set solarmax_2000s_04_ac_output = states('sensor.solarmax_2000s_04_ac_output') | float(default=0) %}
        {% set solarmax_6000s_04_ac_output = states('sensor.solarmax_6000s_04_ac_output') | float(default=0) %}
        {{ solarmax_2000s_04_ac_output > 0 or solarmax_6000s_04_ac_output > 0 }}

- sensor:
    - name: "SolarMax Combined 08 Capacity (installed)"
      device_class: power
      unit_of_measurement: "W"
      state_class: measurement
      state: "{{ states('sensor.solarmax_2000s_22_capacity_installed') | float + states('sensor.solarmax_6000s_22_capacity_installed') | float }}"
      availability: >
        {% set solarmax_2000s_04_ac_output = states('sensor.solarmax_2000s_04_ac_output') | float(default=0) %}
        {% set solarmax_6000s_04_ac_output = states('sensor.solarmax_6000s_04_ac_output') | float(default=0) %}
        {{ solarmax_2000s_04_ac_output > 0 or solarmax_6000s_04_ac_output > 0 }}
  1. If you already have other manually added sensors/templates in your configuration.yaml then you will now also have to move them to individual files in the sensors/templates folder. Remember this is a good thing to do anyway!

  2. Add the following code to your configuration.yaml.

sensor: !include_dir_merge_list sensors/
template: !include_dir_merge_list templates/
  1. Reboot your Home Assistant instance.

References
I would like to thank Niobos for reverse engineering the protocol way before SolarMax provided an official documentation about their MaxComm protocol. Also thanks a lot to Chris for the perl script which helped a lot while troubleshooting.
https://2007.blog.dest-unreach.be/2009/04/15/solarmax-maxtalk-protocol-reverse-engineered/

Thank you very much @Dbuckley1712 for providing the first working example for use with Home Assistant.
https://community.home-assistant.io/t/solarmax-inverter-integration/327723/5

Furthermore the appreciation goes to SOLARMAX GmbH (formerly Sputnik Engineering AG) for providing an official documentation of the involved MaxComm protocol.
https://www.solarmax.com/wp-content/uploads/MaxComm_Protokollbeschreibung_DE.pdf

3 Likes

Thanks for your solution. I have two Solarmax: 3000s and 4200s. I could only receive the datas of the first inverter. With Maxtalk and Solarview I could receive both over the ethernet. Device Adress is also set as 001 and 002. Any idea what could be wrong?

Ich hatte dasselbe Problem. Aus dem zweiten Wechselrichter wurden keine Daten geladen.
Ursache ist vermutlich der erforderliche Zeitversatz. In der MaxComm_Protokollbeschreibung (siehe oben) steht unter 1.2:
Zu einem bestimmten Zeitpunkt darf immer nur ein Gerät abgefragt werden. Das nächste Gerät darf erst abgefragt werden, wenn vom vorher abgefragten Gerät eine Antwort eingetroffen ist oder dessen Antwort-Timeout abgelaufen ist. Die maximale Antwortzeit ist abhängig von der Anzahl der abgefragten Werte:
• typische Antwortzeit: 300 ms
• maximale Antwortzeit (Timeout): 3000 ms

Der Befehl “message_wait_milliseconds” gilt leider nur unter modbus und letzteres habe ich für die S-Serie nicht zum laufen bekommen.

Bei mir hat es aber mit der Verwendung von unterschiedlichen Scan-Intervallen funktioniert, wobei es ausreicht, wenn keine gleichen Intervalle hintereinander verwendet werden.

# Auslesen der Wechselrichter als String
sensor:
  - platform: tcp
    scan_interval: 10           # in Sekunden
    name: "solarmax6000s_1"     # 1. Wechselrichter
    host: 192.168.xxx.xxx
    port: 12345 
    # Adresse:11->0Bhex, Länge:130->82hex, Checksumme:2296
    payload: "{FB;0B;82|64:UDC;IDC;UL1;IL1;PAC;PRL;TNF;KDY;KLD;KMT;KLM;KYR;KLY;KT0;TKK;SYS;KHR;CAC;TYP;SWV;BDN;ADR;PIN;DDY;DMT;DYR;TMI;THR|2296}"

  - platform: tcp
    scan_interval: 9            # in Sekunden
    name: "solarmax6000s_2"     # 2. Wechselrichter
    host: 192.168.xxx.xxx
    port: 12345 
    # Adresse:12->0Chex, Länge:130->82hex, Checksumme:2297
    payload: "{FB;0C;82|64:UDC;IDC;UL1;IL1;PAC;PRL;TNF;KDY;KLD;KMT;KLM;KYR;KLY;KT0;TKK;SYS;KHR;CAC;TYP;SWV;BDN;ADR;PIN;DDY;DMT;DYR;TMI;THR|2297}"

  - platform: tcp
    scan_interval: 10           # in Sekunden
    name: "solarmax6000s_3"     # 3. Wechselrichter
    host: 192.168.xxx.xxx
    port: 12345 
    # Adresse:13->0Dhex, Länge:130->82hex, Checksumme:2298
    payload: "{FB;0D;82|64:UDC;IDC;UL1;IL1;PAC;PRL;TNF;KDY;KLD;KMT;KLM;KYR;KLY;KT0;TKK;SYS;KHR;CAC;TYP;SWV;BDN;ADR;PIN;DDY;DMT;DYR;TMI;THR|2298}"

Danke für das Tutorial. Das war wirklich hilfreich.

HI,
after a few months of use, I made some updates to ha and it stopped working, now I don’t know what to do, has anything changed in the configs after these updates? I hope someone can help me, thanks in advance

Hello,
Thanks for this tutorial. I added solarmax status text enum template…

    - sensor:
        - name: "SolarMax Status"     
          unique_id: solarmax_status
          device_class: enum
          state: >
              {% set mapper =  {
                  '20002' : 'Radiation too low',
                  '20003' : 'Startup',
                  '20004' : 'MPP operation',
                  '20005' : 'MPP operation',
                  '20006' : 'Power limit',
                  '20008' : 'Mains operation',
                  '20115' : 'No mains',
                  '20116' : 'Mains freq high',
                  '20117' : 'Mains freq low'} %}
              {% set state =  states('sensor.solarmax_15_operating_mode') %}
              {{ mapper[state] if state in mapper else 'Unknown' }}