Mqtt sensor - how to load attributes

Hello
I have a multiple sensors for shelly devices, each one representing state, battery, tilt etc.
I would like to have all those values in single sensors. Secondary values like battery or tilt could be places as attributes.

I’m struggling to achieve that.
how can I create such sensor, which automatically reads values from topic into attributes?

Lets’s be the code below a starting point:

  - platform: mqtt
    name: "PCroom Window"
    state_topic: "shellies/shellydw-pc/sensor/state"
    payload_on: "open"
    payload_off: "close"
    device_class: "window"
    json_attributes_topic: "shellies/shellydw-pc/sensor/"

I’ve added json_attributes_topic believing that it’s enough. but it’s not.

here is how the message structure looks like:

obrazek

Any help appreciated.

json_attributes_topic allows you to specify one MQTT topic that receives a payload containing a dictionary in JSON format. For example:

{"tilt": -1, "vibration": 0, "lux": 1838, "battery": 93}

It can readily convert that into attributes. If the JSON structure is more complicated, one can specify a template to extract the names and values using json_attributes_template.

In your case, there is no single topic containing all the desired attributes; each has its own topic.

I though shellydw-pc/sensor is the topic containing all attributes (state, tilt, vibration, lux, battery). But obviously I was wrong.
How can I use json_attributes_template then? All documentation I found works with single attribute. I haven’t succeed so far applying it to my case.

thank you

The option you have is to create mqtt sensors for all the topics you want.

Is there the only option? As I wrote in OP I don’t need all those values to be tracked by sensors.
Actually I have them already as sensors but I found it overengeenered. instead of 15 sensors I have 45. it’s insufficient.
I’d like to have them as attributes, without need of creating sensors.

Here’s an example of using json_attributes_template.

If given this topic:

sensor/cpu

and this payload:

{
	"used_space": 25,
	"sys_clock_speed": 1500,
	"data": {
		"cpu_temp": 43.0,
		"voltage": 0.8500,
		"cpu_load": 1.25
	},
	"memory": "False",
	"swap": "False"
}

This MQTT Sensor extracts values from the payload and assigns them to attributes using custom names.

  - platform: mqtt
    name: monitor
    state_topic: sensor/cpu
    value_template: "{{ value_json.used_space }}"
    json_attributes_topic: sensor/cpu
    json_attributes_template: >
      { "speed": {{value_json.sys_clock_speed}},
        "temperature": {{value_json.data.cpu_temp}},
        "voltage": {{value_json.data.voltage}},
        "load": {{value_json.data.cpu_load}},
        "memory": "{{value_json.memory}}",
        "swap": "{{value_json.swap}}" }

If the our data you wish to use for attributes is not published to a single topic then json_attributes_topic and json_attributes_template probably can’t help you.

I say “probably” because there is one thing I have not tried. You can try setting json_attributes_topic to:

shellies/shellydw-pc/sensor/#

That’s a ‘wild card’ character and means to subscribe to all topics below shellies/shellydw-pc/sensor. If that is even allowed in this context, the next challenge is composing a template that understands what was just received and to which attribute it belongs to. The only thing it will receive (if it works) will be the raw data and won’t know if it belongs to tilt or lux or whatever.

4 Likes

I carried out an experiment and the results don’t bode well for your application.

I created this MQTT sensor:

  - platform: mqtt
    name: "test sensor1"
    state_topic: "test/sensor1"
    json_attributes_topic: "test/sensor1/+"
    json_attributes_template: >
      {"other_data":"{{value}}"}

Note the plus symbol at the end of json_attributes_topic. That means to subscribe to all sub-topics of test/sensor1 but not test/sensor1 itself.

  1. When I publish 22 to test/sensor1 it becomes the sensor’s state value.
  2. When I publish 150 to test/sensor1/whatever it becomes the value of an attribute named other_data.

Screenshot from 2020-07-18 16-28-44

The limitation is that if now publish hello to test/sensor1/something it will replace the existing value of other_data. The template has no means of determining which sub-topic received the payload. Without knowing the payload’s source, it can’t assign it to a different attribute. For what you want to do, that’s a showstopper.


NOTE

The only possible workaround I can think of is if the values for tilt, vibration, lux, and battery are distinctly different. For example, if the value of vibration can only be a negative number then any received negative numbers can be presumed to belong to vibration. However, I doubt that’s the case here. the value of lux can easily overlap with the permissible range of values for battery so there’s no uniqueness that can be used to differentiate the source of the data.

1 Like

Thank-you so much, this great write up coupled with using MQTTExplorer and I can finally use attributes.

I notice the double quotes in the second line, and then I am confused

It depends on whether you want the JSON value to be interpreted as a string or a number (or another type like boolean, list, etc).

Look at the example posted in the Syntax section of this Wikipedia entry for JSON. Notice how number values are not wrapped in quotes?

1 Like