Reading complcated mqtt output

I do have a couple of BLE beacon readers that sends a complicated string, like:


The first par tof the string is not difficult. I can get that with the template-trigger to an entity.
The last part is harder. I can do

state: "{{ (trigger.payload | from_json).devices[1] }}"

But: it are a lot of items and the number of items changes every time there come new data.

I do want to know if a specific beacon is seen (so if the mac adress is in the mqtt file, that is the second item) and from two items I want to get more information (rssi value, what is the third item)

Is there a way to put the complete json file to an entity (from what I can extract the needed information) or is there another way to deal with this?

Yes. I assume you’ve read the docs to create MQTT sensors?

Something like this should work for value_template:

value_template: "{{ (value_json['devices']|selectattr(1,'equalto','30AD2A354CDE')|list)[0][2] }}"

That should return the third element (RSSI) for the first item matching that 30AD... MAC address. The 1 in the selectattr statement is reading the second element in the list item and comparing with the hard-coded MAC address. The template tool is great for homing in on what you need: just work iteratively:

The data in the example you posted contains multiple instances of data for the same MAC address. For example, there are four instances for 30AD2A354CDE.

How do you want to handle that? Just use the first instance found for 30AD2A354CDE?

Starting from the string converted into a dictionnary

  "v": 1,
  "mid": 1503,
  "time": 2918,
  "ip": "",
  "mac": "E0E2E69D1984",
  "rssi": -72

You can access any of the item like so

{% if (beacon["mac"]) == "E0E2E69D1985" %}
  {{ beacon["mid"] }}
{% else %}
  {{ beacon["ip"] }}
{% endif %}

This will give you as it is not the mac address from the string.
On the other hand

{% set beacon = ('{"v":1,"mid":1503,"time":2918,"ip":"","mac":"E0E2E69D1984","rssi":-72}' | from_json) %}
{% if (beacon["mac"]) == "E0E2E69D1984" %}
  {{ beacon["mid"] }}
{% else %}
  {{ beacon["ip"] }}
{% endif %}

Will give you 1503 as it is the mac address from the string.
Hope that helps.

EDIT: As you have multiple elements with the same key, you can also loop with the for command

I need only a few mac-adresses, not the ones that are double. So I simply ignore them

Perfect, did exactly what I wanted.


I was a bit over-enthousiast.
The sollution

value_template: "{{ (value_json['devices']|selectattr(1,'equalto','30AD2A354CDE')|list)[0][2] }}"

worked great to seperate the values.

I tried

value_template: {{ (value_json['devices']) }}

to get the whole string in a sensor, so I can find out if a certain mac-adress is present.
This shows the good outcome in the template editor.

Did do that in configuration.yaml with:

  - name: "MQTT totaal"
    state_topic: "Garage"
    unique_id: mqtt_totaal
    value_template: "{{ (value_json['devices']) }}"

So basically the same as with the selectattr.

But this one gives as value ‘unknown’

What do I wrong?

States cannot exceed 256 characters.

OK, that’s the problem. Thanks!