Siemens LOGO MQTT based Sensors - shared topic for multiple sensors problem

I was able to integrate LOGO 8.4 with Home Assistant using MQTT successfully. I used https://www.youtube.com/watch?v=3QG-qFuS1cw as a guide.

I’ve added the below lines to my configuration:

mqtt:
  sensor:
    - name: "I1"
      state_topic: "LOGO_Pub"
      value_template: "{{ value_json['state']['reported']['I1']['value'][0] }}"
    - name: "I2"
      state_topic: "LOGO_Pub"
      value_template: "{{ value_json['state']['reported']['I2']['value'][0] }}"
    - name: "I3"
      state_topic: "LOGO_Pub"
      value_template: "{{ value_json['state']['reported']['I3']['value'][0] }}"
    - name: "I4"
      state_topic: "LOGO_Pub"
      value_template: "{{ value_json['state']['reported']['I4']['value'][0] }}"

basically, it works, but I started getting errors in logs:

2024-10-24 11:21:59.260 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'I4' (value: {"state":{"reported":{"$logotime":1729768864}}}, template: {{ value_json['state']['reported']['I4']['value'][0] }})
2024-10-24 11:22:09.262 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'I4' (value: {"state":{"reported":{"$logotime":1729768874}}}, template: {{ value_json['state']['reported']['I4']['value'][0] }})
2024-10-24 11:22:19.263 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'I4' (value: {"state":{"reported":{"$logotime":1729768884}}}, template: {{ value_json['state']['reported']['I4']['value'][0] }})
2024-10-24 11:22:29.262 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'I4' (value: {"state":{"reported":{"$logotime":1729768894}}}, template: {{ value_json['state']['reported']['I4']['value'][0] }})
2024-10-24 11:22:39.261 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'I4' (value: {"state":{"reported":{"$logotime":1729768904}}}, template: {{ value_json['state']['reported']['I4']['value'][0] }})
2024-10-24 11:22:49.260 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'I4' (value: {"state":{"reported":{"$logotime":1729768914}}}, template: {{ value_json['state']['reported']['I4']['value'][0] }})
2024-10-24 11:22:59.261 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'I4' (value: {"state":{"reported":{"$logotime":1729768924}}}, template: {{ value_json['state']['reported']['I4']['value'][0] }})
2024-10-24 11:23:09.257 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'I4' (value: {"state":{"reported":{"$logotime":1729768934}}}, template: {{ value_json['state']['reported']['I4']['value'][0] }})
2024-10-24 11:23:19.257 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'I2' (value: {"state":{"reported":{"$logotime":1729768944}}}, template: {{ value_json['state']['reported']['I2']['value'][0] }})
2024-10-24 11:23:19.261 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'I3' (value: {"state":{"reported":{"$logotime":1729768944}}}, template: {{ value_json['state']['reported']['I3']['value'][0] }})
2024-10-24 11:23:19.262 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'I4' (value: {"state":{"reported":{"$logotime":1729768944}}}, template: {{ value_json['state']['reported']['I4']['value'][0] }})

The problem is that LOGO is sending the data to a single topic (this can’t be changed).
So when the value for I1 is changed, the state is sent to my topic, but all sensors try to get the value and three will throw errors (assuming I have 4 sensors)

Has anyone had a similar issue, when the same Topic is shared between multiple sensors?

Is there a way in value_template to trigger value change when a specific JSON element is found?

EDIT:
I got a partial solution based on Adjusting template to obtain value from only one kind of MQTT message and ignore others - #2 by 123

mqtt:
  sensor:
    - name: "I1"
      state_topic: "LOGO_Pub"
      value_template: "{{ value_json.state.reported.I1.value[0] if value_json.state.reported.I1 is defined else this.state }}"
    - name: "I2"
      state_topic: "LOGO_Pub"
      value_template: "{{ value_json.state.reported.I2.value[0] if value_json.state.reported.I2 is defined else this.state }}"
    - name: "I3"
      state_topic: "LOGO_Pub"
      value_template: "{{ value_json.state.reported.I3.value[0] if value_json.state.reported.I3 is defined else this.state }}"
    - name: "I4"
      state_topic: "LOGO_Pub"
      value_template: "{{ value_json.state.reported.I4.value[0] if value_json.state.reported.I4 is defined else this.state }}"

but now I get an error when I restart HA:

Rejestrator: homeassistant.components.mqtt.models
Źródło: components/mqtt/models.py:366
integracja: MQTT (dokumentacja, Problemy)
Pierwsze zdarzenie: 12:24:16 (2 zdarzenia)
Ostatnio zalogowany: 12:24:16

Exception raised while updating state of sensor.ai2, topic: 'LOGO_Pub' with payload: b'{"state":{"reported":{"$logotime":1729772603}}}'
Exception raised while updating state of sensor.ai1, topic: 'LOGO_Pub' with payload: b'{"state":{"reported":{"$logotime":1729772603}}}'
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/sensor/__init__.py", line 657, in state
    numerical_value = int(value)
                      ^^^^^^^^^^
ValueError: invalid literal for int() with base 10: 'unknown'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/sensor/__init__.py", line 660, in state
    numerical_value = float(value)
                      ^^^^^^^^^^^^
ValueError: could not convert string to float: 'unknown'

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

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/mqtt/models.py", line 366, in process_write_state_requests
    entity.async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1005, in async_write_ha_state
    self._async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1130, in _async_write_ha_state
    self.__async_calculate_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1067, in __async_calculate_state
    state = self._stringify_state(available)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1011, in _stringify_state
    if (state := self.state) is None:
                 ^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/sensor/__init__.py", line 664, in state
    raise ValueError(
ValueError: Sensor sensor.ai2 has device class 'None', state class 'None' unit 'V' and suggested precision 'None' thus indicating it has a numeric value; however, it has the non-numeric value: 'unknown' (<class 'str'>)

After restart all my sensors are unknown, so I’m not sure what else I must configure

This is one of the sensors that has an error.
Likely, you don’t properly handle availability (“unknown”, “unavailable” states).

When I restart Home Assistant, all of them show unknown. When I do something on LOGO (publish a message to my topic), everything returns to normal.

Please show the definition of, e.g., sensor.ai2

Below are my current definitions:

mqtt:
  sensor:
    - name: "I1"
      state_topic: "LOGO_Pub"
      value_template: "{{ value_json.state.reported.I1.value[0] if value_json.state.reported.I1 is defined else this.state }}"
    - name: "I2"
      state_topic: "LOGO_Pub"
      value_template: "{{ value_json.state.reported.I2.value[0] if value_json.state.reported.I2 is defined else this.state }}"
    - name: "I3"
      state_topic: "LOGO_Pub"
      value_template: "{{ value_json.state.reported.I3.value[0] if value_json.state.reported.I3 is defined else this.state }}"
    - name: "I4"
      state_topic: "LOGO_Pub"
      value_template: "{{ value_json.state.reported.I4.value[0] if value_json.state.reported.I4 is defined else this.state }}"
#ANALOG INPUT
    - name: "AI1"
      state_topic: "LOGO_Pub"
      value_template: "{{ value_json.state.reported.AI1.value[0] if value_json.state.reported.AI1 is defined else this.state }}"
      unit_of_measurement: "V"
    - name: "AI2"
      state_topic: "LOGO_Pub"
      value_template: "{{ value_json.state.reported.AI2.value[0] if value_json.state.reported.AI2 is defined else this.state }}"
      unit_of_measurement: "V"

As I said, you should handle availability, e.g.

      availability: "{{ True if value_json.state.reported.AI2 is defined and value_json.state.reported.AI2.value[0] | is_number else False }}"

Thank you for the reply, but I think this won’t work.
I will get true for AI2 if I update AI2, but when I update AI1 then AI2 will be set tu unavailable, because as mentioned SIemens LOGO is sending everything to the same topic.

So if I update AI1 on LOGO, then AI1 will ba available, AI2 will be unavailable, if I update AI2 it will be available, but AI1 won’t.

I’ll check that as soon as possible

Yes, it’s a common challenge; multiple data values are “multiplexed” on a single channel (i.e. one MQTT topic).

What I have recommended for this situation is to use a simple automation to “demultiplex” the data; effectively, each value is assigned a separate MQTT topic.

Details and examples can be found in this post:

Let me know if you need assistance to implement it.

Thank you for the reply and for the link.
I looked at the proposed solutin, but when I subscribe to my topic I see this kind of messages:

{
    "state": {
        "reported": {
            "I3": {
                "desc": "I-bit-3-1",
                "value": [
                    1
                ]
            },
            "AI1": {
                "desc": "AI-word-1-1",
                "value": [
                    0
                ]
            },
            "AI2": {
                "desc": "AI-word-2-1",
                "value": [
                    0
                ]
            },
            "AI3": {
                "desc": "AI-word-3-1",
                "value": [
                    170
                ]
            },
            "$logotime": 1729779769
        }
    }
}

or

{
    "state": {
        "reported": {
            "I3": {
                "desc": "I-bit-3-1",
                "value": [
                    0
                ]
            }
            "$logotime": 1729779769
        }
    }
}

LOGO can send a single value or multiple values in one message.
I’m not sure if a singlke automation can handle this.

I have this automation:

alias: LOGO AI1
description: ""
triggers:
  - trigger: mqtt
    topic: LOGO_Pub
conditions:
  - condition: template
    value_template: "{{true if trigger.payload_json.state.reported.AI1 is defined else false}}"
actions:
  - action: mqtt.publish
    metadata: {}
    data:
      retain: true
      topic: LOGO/AI1
      payload: "{{ trigger.payload_json.state.reported.AI1.value[0] }}"
mode: single

and I think it will work for a single sensor, but not sure if I can use a single Automation for all sensors that publish to LOGO_Pub

Your example is hard-coded to handle a single data value. Review the examples I posted which are all designed to dynamically publish any one of multiple data values to its own unique topic.

I’m aware of that because I don’t know how to handle multiple sensor values in a single message.

Take a look at samples I posted in Siemens LOGO MQTT based Sensors - shared topic for multiple sensors problem - #9 by Misiu.

If there would be always a single sensor in payload I think it would be doable, but I do not know how to iterate over state.reported items that have value property, and send a message for each item in a separate topic.

Can I use a repeat block with a variable?
So in the first step, I would collect keys (sensor names) and then iterate over them with a single action.

I tested the following automation using your sample data and it successfully published each data value to a separate, unique topic.

alias: LOGO
description: ""
triggers:
  - platform: mqtt
    topic: LOGO_Pub
conditions: []
actions:
  - repeat:
      for_each: "{{ (trigger.payload_json.state.reported.keys() | list)[:-1] }}"
      sequence:
        - action: mqtt.publish
          data:
            retain: true
            topic: "LOGO/{{ repeat.item }}"
            payload: "{{ trigger.payload_json.state.reported.get(repeat.item)['value'][0] }}"
mode: single

Screenshot from MQTT Explorer

Final step is to define the sensors. Here’s a minimal configuration.

mqtt:
  sensor:
    - name: "I1"
      state_topic: "LOGO/I1"
    - name: "I2"
      state_topic: "LOGO/I2"
    - name: "I3"
      state_topic: "LOGO/I3"
    - name: "I4"
      state_topic: "LOGO/I4"
    - name: "AI1"
      state_topic: "LOGO/AI1"
      unit_of_measurement: "V"
    - name: "AI2"
      state_topic: "LOGO/AI2"
      unit_of_measurement: "V"

I did a quick test and it seems to work.

This is my variation using variables:

alias: LOGO
description: Quick test
triggers:
  - trigger: mqtt
    topic: LOGO_Pub
    variables:
      vars: "{{ (trigger.payload_json.state.reported.keys() | list)[:-1] }}"
conditions:
  - condition: template
    value_template: "{{ vars | length > 0 }}"
actions:
  - repeat:
      for_each: "{{ vars }}"
      sequence:
        - action: mqtt.publish
          metadata: {}
          data:
            retain: true
            topic: LOGO/{{ repeat.item }}
            payload: "{{ trigger.payload_json.state.reported.get(repeat.item)['value'][0] }}"
mode: single

Not sure if it will perform better or worse, but I saw in one of your posts that we can have variables in triggers, so I used them.
Sadly we can’t see them in visual editor, but that’s not a problem, as I only need a single automation for all LOGO sensors.

Is it possible for the received payload to not have any data?

The reason why I ask is that the Template Condition you created checks if vars contains more than zero items. The two data samples you had provided contain at least one item.

Every ten seconds Siemens LOGO sends this message:

{
    "state": {
        "reported": {
            "$logotime": 1729844237
        }
    }
}

so I intentionally added this condition.

@123 Everything works fine, the values persist when I restart HA.
I noticed one thing. I made some changes to LOGO and it stopped sending updates via MQTT. I was thinking that everything works just fine, because the values persist when I restart HA.
LOGO 8.4 doesn’t have LWT (I got this confirmed from Siemens), so I’m wondering if there is a simple workaround.
Can I check if any value is sent to LOGO_Pub, if there is no message for last 2 minutes mark all as unavailable, or maybe send LWT message to all sensors.

Any hints on how to do this?

It implies the values are published as retained messages. That means they’re stored by the broker and made available to Home Assistant (or any other MQTT client) upon connection to the broker.

If you have the ability to reconfigure LOGO, perhaps you can disable publishing with the ‘retained message’ feature. The values will always be unavailable when Home Assistant is restarted (and change only when new values are published).

Perhaps this post can serve as inspiration for creating an automation that periodically checks for “stale” values and then publishes unavailable to their respective MQTT topics.

Thank you for such a fast reply.
The retain flag is set by automation you helped me build. I’m aware that this flag helps and causes trouble.
One option is to remove it, and then when I restart HA, I will get unavailable, but this won’t solve the problem when LOGO crashes.
I’ll try to create a second automation to send LWT messages when there is no message for a given time.

What do you think about such automation?

description: ""
mode: restart
triggers:
  - trigger: mqtt
    topic: LOGO_Pub
  - trigger: homeassistant
    event: start
actions:
  - delay:
      hours: 0
      minutes: 2
      seconds: 0
      milliseconds: 0
  - action: mqtt.publish
    metadata: {}
    data:
      evaluate_payload: false
      qos: 0
      topic: LOGO\LWT
      payload: Offline

Then I could add this to my sensors:

availability:
    - topic: "LOGO\LWT"
      payload_available: "Online"
      payload_not_available: "Offline"

This is just a quick idea, need to test it.

I don’t know which method will be more efficient because my automation will be called every time an MQTT message is sent, but yours will query all entities every X minutes.