SunSpec / modbus TCP problem

Hi, I am trying to directly read an inverter with Solaredge inverter and meter via Modbus TCP. It communicates with SunSpec protocol, I saw that there is integration, but it has problems with scaling and the author has not responded for a long time. SunSpec for each quantity gives you two Modbus address the value and scale (which keeps changing). I would like to access the inverter directly and not use extensions that depend on the developer and solaredge. I have tried to do it myself, but the continuous scale changes lead to incorrect values, especially in the variations. I have modified the code so that it only calculates when the scale has not changed recently, but I keep getting absurd values 2/3 times a day. Sometimes they look like Modbus read errors, but sometimes they look like calculation errors.
Here is the code that goes to read the modbus data:

- name: "SolarEdge"
  type: tcp
  host: "192.168.1.9" # Sostituisci con l'indirizzo IP del tuo inverter
  port: 1502 # Porta predefinita per Modbus TCP
  sensors:
    - name: "Scala_W_pensiline_L"
      address: 40084
      input_type: holding
      data_type: int16
      unit_of_measurement: ""
      scale: 1
      state_class: measurement
      scan_interval: 30

    - name: "Pensiline_Potenza_L"
      address: 40083 # Registro SunSpec per la potenza AC
      input_type: holding
      data_type: int16
      scale: 1
      unit_of_measurement: "W"
      device_class: power
      state_class: measurement
      scan_interval: 30

Here the one that calculates the derived values

sensor:
      pensiline_potenza:
        unique_id: "id_pensiline_potenza"
        friendly_name: "Pensiline Potenza"
        unit_of_measurement: "kW"
        device_class: power
        value_template: >-
          {% set s1 = states('sensor.Pensiline_Potenza_L') %}
          {% set s2 = states('sensor.Scala_W_pensiline_L') %}
          {% set scale_last_change = as_timestamp(states.sensor.Scala_W_pensiline_L.last_changed) %}
          {% set now_ts = as_timestamp(now()) %}
          {% if (now_ts - scale_last_change) < 5 %}
            {{ none }}
          {% else %}
            {% if s1 not in ['unknown', 'unavailable', None] and s2 not in ['unknown', 'unavailable', None] %}
              {{ (s1 |float (0) * 10**(s2 |float (0))) / 1000 | round(2) }}
            {% else %}
              {{ none }}
            {% endif %}
          {% endif %}

Do you have any suggestions to eliminate these error? It would be fine for me to simply eliminate them when absurd. Many thanks

I wrote an integration for SolarEdge, which I recommend instead of trying to read modbus values directly:

The problem with modbus sensors is that the scale value on the inverter can change between reads, which gives you bad values. The only way to match scales and values is to read them at the same in a single read, which modbus integration can not do.

Many thanks for your reply, I was just trying to read the values at the same time, are you sure you can’t? I was trying like this:

- name: "Correnti_Complete"
  address: 40191 # Primo registro della serie (corrente Fase A)
  input_type: holding
  count: 4 # Legge 4 registri consecutivi (40191, 40192, 40193, 40194)
  data_type: custom
  structure: ">hhh h" # 3 valori int16 + 1 valore int16 (scala)
  scan_interval: 10

Can it work? Work in progress, now I’ve no time to test.

Well, my experience is it was easier creating a custom integration instead of trying to get core modbus to work with all the quirks of SolarEdge inverters. So I recommend my integration because I’ve already done all the hard work.

If you want to keep trying modbus then I would recommend looking through my code to find all the methods and tests I’ve had to use to keep the data clean.

many thanks, you are very kind!