Help integrating a modbus device

Hello, I just got an inverter that doesn’t have direct Home Assistant integration, but it has modbus support. I set up these sensors that I copied from someone who is using the same hardware as I do, but I am not able to see any of these sensors anywhere. Where should I be looking for them?

- type: tcp
  name: "solar"
  host: 192.168.0.153
  port: 502
  sensors:
    - name: Solar Potencia Grid
      scan_interval: 5
      data_type: int16
      input_type: input
      unit_of_measurement: W
      slave: 1
      address: 71
      unique_id: sensor.solar_potencia_grid
    - name: Solar Potencia Bateria
      scan_interval: 5
      data_type: int16
      input_type: input
      unit_of_measurement: W
      slave: 1
      address: 19
      unique_id: sensor.solar_potencia_bateria
    - name: Solar Potencia Inversor grid
      scan_interval: 5
      data_type: int16
      input_type: input
      unit_of_measurement: W
      slave: 1
      address: 51
      unique_id: sensor.solar_potencia_inversor_grid
    - name: Solar Potencia Inversor criticas
      scan_interval: 5
      data_type: int16
      input_type: input
      unit_of_measurement: W
      slave: 1
      address: 46
      unique_id: sensor.solar_potencia_inversor_criticas
    - name: Solar Potencia Inversor
      scan_interval: 5
      data_type: int16
      input_type: input
      unit_of_measurement: W
      slave: 1
      address: 37
      unique_id: sensor.solar_potencia_inversor
    - name: Solar Potencia PV1
      scan_interval: 5
      data_type: int16
      input_type: input
      unit_of_measurement: W
      slave: 1
      address: 33
      unique_id: sensor.solar_potencia_pv1
    - name: Solar Potencia PV2
      scan_interval: 5
      data_type: int16
      input_type: input
      unit_of_measurement: W
      slave: 1
      address: 36
      unique_id: sensor.solar_potencia_pv2
    - name: Solar bateria carga
      scan_interval: 15
      data_type: uint16
      input_type: input
      unit_of_measurement: "%"
      slave: 1
      address: 20
      unique_id: sensor.solar_bateria_carga
      

I restarted Home Assistant, and I see that it has been connected to the device because I see connections on it every 5 seconds. But, I found on my log some template errors when I tried to use these values:

Logger: homeassistant.helpers.event
Source: helpers/template.py:643
First occurred: 18:18:07 (6 occurrences)
Last logged: 18:18:08

Error while processing template: Template<template=({% set pv1 = states('sensor.solar_potencia_pv1') | float %} {% set pv2 = states('sensor.solar_potencia_pv2') | float %} {{ ((pv1 + pv2)) | round(0, default=0) }}) renders=2>
Error while processing template: Template<template=({% if states('sensor.solar_potencia_bateria')|float <= 0 %} {{ -((states('sensor.solar_potencia_bateria'))|int) }} {% endif %}) renders=2>
Error while processing template: Template<template=({% if states('sensor.solar_potencia_bateria')|float >= 0 %} {{ (states('sensor.solar_potencia_bateria')) }} {% endif %}) renders=2>
Error while processing template: Template<template=({% if states('sensor.solar_potencia_grid')|float <= 0 %} {{ -((states('sensor.solar_potencia_grid'))|int) }} {% endif %}) renders=2>
Error while processing template: Template<template=({% if states('sensor.solar_potencia_grid')|float >= 0 %} {{ (states('sensor.solar_potencia_grid')) }} {% endif %}) renders=2>
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 2307, in strptime
    return datetime.strptime(string, fmt)
           ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/_strptime.py", line 674, in _strptime_datetime
    tt, fraction, gmtoff_fraction = _strptime(data_string, format)
                                    ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/_strptime.py", line 453, in _strptime
    raise ValueError("time data %r does not match format %r" %
                     (data_string, format))
ValueError: time data '1' does not match format '%Y-%m-%dT%H:%M:%S.%fZ'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 641, in async_render
    render_result = _render_with_context(self.template, compiled, **kwargs)
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 2977, in _render_with_context
    return template.render(**kwargs)
           ~~~~~~~~~~~~~~~^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/jinja2/environment.py", line 1295, in render
    self.environment.handle_exception()
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "/usr/local/lib/python3.13/site-packages/jinja2/environment.py", line 942, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 1, in top-level template code
  File "/usr/local/lib/python3.13/site-packages/jinja2/sandbox.py", line 401, in call
    return __context.call(__obj, *args, **kwargs)
           ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 2310, in strptime
    raise_no_default("strptime", string)
    ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 1975, in raise_no_default
    raise ValueError(
    ...<2 lines>...
    )
ValueError: Template error: strptime got invalid input '1' when rendering template '{% set t = now() %} {{ relative_time(strptime(states.input_text.esomeprazol_last.state,"%Y-%m-%dT%H:%M:%S.%fZ" )) }}' but no default was specified

The above exception was the direct cause of the following exception:

This is the template sensors that I’m using:

- sensor: 
  - name: "Solar Potencia PV"
    unit_of_measurement: "W"
    state: > 
      {% set pv1 = states('sensor.solar_potencia_pv1') | float %}
      {% set pv2 = states('sensor.solar_potencia_pv2') | float %}
      {{ ((pv1 + pv2)) | round(0, default=0) }}
    unique_id: sensor.solar_potencia_pv
  - name: "Solar Potencia Bateria Carga"
    unit_of_measurement: "W"
    state: >
      {% if states('sensor.solar_potencia_bateria')|float <= 0 %}
      {{ -((states('sensor.solar_potencia_bateria'))|int) }} 
      {% endif %}
    unique_id: sensor.solar_potencia_bateria_carga
  - name: "Solar Potencia Bateria Descarga"
    unit_of_measurement: "W"
    state: >
      {% if states('sensor.solar_potencia_bateria')|float >= 0 %}
      {{ (states('sensor.solar_potencia_bateria')) }}
      {% endif %}
    unique_id: sensor.solar_potencia_bateria_descarga
  - name: "Solar Potencia Red Volcado"
    unit_of_measurement: "W"
    state: >
      {% if states('sensor.solar_potencia_grid')|float <= 0 %}
      {{ -((states('sensor.solar_potencia_grid'))|int) }} 
      {% endif %}
    unique_id: sensor.solar_potencia_red_volcado
  - name: "Solar Potencia Red Consumo"
    unit_of_measurement: "W"
    state: >
      {% if states('sensor.solar_potencia_grid')|float >= 0 %}
      {{ (states('sensor.solar_potencia_grid')) }}
      {% endif %}
    unique_id: sensor.solar_potencia_red_consumo

It’s worth noticing that I don’t see any of the sensors coming from the tcp integration, only the ones from the template appear in the UI and they appear as unavailable.

For reference, this is the repository I pick the files from:

Ok, I had to do a COMPLETE restart of home assistant.
Now, how can I make this be part of the energy panel?

1 Like

That specific error is unrelated to anything in that configuration.

You do have some errors related to those templates, specifically you aren’t providing a default.

Either use an availability: template or provide defaults to float.

Lastly, to add to statistics, you need to provide the entities with a state_class, device_class and a unit_of_measurement and your state can never resolve any values aside from a number or the value None.

You picked the latest error, which I accidently copied too. What about the ones at the top?

About the state class, what do I need to modify in my config to add them?

You need to add state_class: measurement and device_class: power to your template sensors. This will allow you to have statistics on those entities. Those entities still are power entities, not energy. So you’ll need a second set of entities that converts power to energy. The integration integration does that.

1 Like

There’s the lack of an else case in the last four templates as well.

- sensor: 
  - name: "Solar Potencia PV"
    unique_id: sensor.solar_potencia_pv
    unit_of_measurement: "W"
	state_class: measurement
	device_class: power
    state: > 
      {% set pv1 = states('sensor.solar_potencia_pv1') | float %}
      {% set pv2 = states('sensor.solar_potencia_pv2') | float %}
      {{ (pv1 + pv2) | round(0, default=0) }}
	availability: >
	  {{ has_value('sensor.solar_potencia_pv1') and has_value('sensor.solar_potencia_pv2') }}

  - name: "Solar Potencia Bateria Carga"
    unique_id: sensor.solar_potencia_bateria_carga
    unit_of_measurement: "W"
	state_class: measurement
	device_class: power
    state: >
      {% if states('sensor.solar_potencia_bateria')|float <= 0 %}
        {{ states('sensor.solar_potencia_bateria')|float|abs }} 
	  {% else %}
	    0
      {% endif %}
	avalability: >
	  {{ has_value('sensor.solar_potencia_bateria') }}

  - name: "Solar Potencia Bateria Descarga"
    unique_id: sensor.solar_potencia_bateria_descarga
    unit_of_measurement: "W"
	state_class: measurement
	device_class: power
    state: >
      {% if states('sensor.solar_potencia_bateria')|float >= 0 %}
        {{ states('sensor.solar_potencia_bateria') }}
	  {% else %}
	    0
      {% endif %}
	avalability: >
	  {{ has_value('sensor.solar_potencia_bateria') }}

  - name: "Solar Potencia Red Volcado"
    unique_id: sensor.solar_potencia_red_volcado
    unit_of_measurement: "W"
	state_class: measurement
	device_class: power
    state: >
      {% if states('sensor.solar_potencia_grid')|float <= 0 %}
        {{ states('sensor.solar_potencia_grid')|float|abs }} 
	  {% else %}
	    0
      {% endif %}
	avalability: >
	  {{ has_value('sensor.solar_potencia_grid') }}

  - name: "Solar Potencia Red Consumo"
    unique_id: sensor.solar_potencia_red_consumo
    unit_of_measurement: "W"
	state_class: measurement
	device_class: power
    state: >
      {% if states('sensor.solar_potencia_grid')|float >= 0 %}
        {{ states('sensor.solar_potencia_grid') }}
	  {% else %}
	    0
      {% endif %}
	avalability: >
	  {{ has_value('sensor.solar_potencia_grid') }}

I have several sensors defined. The first file I posted shows the modbus configuration sensors. Do I need to put the device_class and state_class there too?

1 Like

My editor complains about some of the availability entries:

1 Like

Because apparently I can’t spell “availability”.

1 Like

Ah! I didn’t noticed it either :joy:

1 Like

There are still issues with the templates in that screenshot. You must supply an else case for your if statements.

Yes, yes, I added it to all of them, thanks

1 Like

Those are also power sensors, you need energy sensors. Power is momentary watts. Energy is watts over time. You don’t have energy sensors.

I set all the values in my modbus configuration to be of type power and measurement and also the ones in the templates.
Maybe I need to modify this sensors? This are imported into my config:

- platform: integration
  source: sensor.solar_potencia_bateria_carga
  name: Solar Energía Batería Carga
  unique_id: sensor.solar_energia_bateria_carga
  unit_prefix: k
  unit_time: h
  round: 2
  method: right
- platform: integration
  source: sensor.solar_potencia_bateria_descarga
  name: Solar Energía Batería Descarga
  unique_id: sensor.solar_energia_bateria_descarga
  unit_prefix: k
  unit_time: h
  round: 2
  method: right
- platform: integration
  source: sensor.solar_potencia_pv
  name: Solar Energía PV
  unique_id: sensor.solar_energia_pv
  unit_prefix: k
  unit_time: h
  round: 2
  method: right
- platform: integration
  source: sensor.solar_potencia_red_consumo
  name: Solar Energía Red Consumo
  unique_id: sensor.solar_energia_red_consumo
  unit_prefix: k
  unit_time: h
  round: 2
  method: right
- platform: integration
  source: sensor.solar_potencia_red_volcado
  name: Solar Energía Red Volcado
  unique_id: sensor.solar_energia_red_volcado
  unit_prefix: k
  unit_time: h
  round: 2
  method: right

That should be all you need. When the entities gather history, you’ll be able to set up the energy tab using them.

Yep, that part was key too :joy:
I forgot you have to go to the energy tab and configure them. I expected them to appear automatically. Then I clicked the edit button and it was like an epiphany.
I have now the energy flowing and looking cool:

However, there must be some bug with my modbus sensors, because it says my solar production is 0, and that is simply not true:

which ones are those? Post all configs for them

The templates, the modbus and the energy sensors are all thar I have, already posted. You can have a look at the GitHub repository I posted to see the complete thing except for the fixes that has been suggested in this thread. The screenshot at the bottom is from my inversor status page

Yes but which ones, I can’t read Spanish. Or is it just all of them?

Do you mean in the screenshot or in the config?