How to handle different JSON data from the same Serial port?

Hello, I need advice on how to solve this situation:

I made a LoRa device that receives (USB/serial) JSON messages from the same USB device/port:

{
"from_address": "10",
"device_type": "DOOR",
"device_state": "CLOSE"
}

or

{
"from_address": "25",
"device_type": "DOOR",
"device_state": "CLOSE"
}

or

{
"from_address": "35",
"device_type": "SWITCH",
"device_state": "ACTIVE"
}

How to handle data (“device_type” and “device_state”) based on “from_address”?

Thanks in advance and please answer at beginner level as I am very new to HA!

I’ve been quite impressed with the amount of JSON experts on this huge forum who are willing to give advice…
I know I don’t do nuclear plant management with HA, but maybe there is a subforum section for simple beginner questions like this?

What makes you think this is a simple beginner question? Actually, I would like to learn more about using Lora in Home Assistant.

I don’t have any USB devices, but is the from_address always unique?

Because it is :wink:

Btw LoRa has nothing to do with this, in this case it is a data source, but it would be the same if I had a central heating system (or anything else) with a serial output (or any other) and messages about temperature, humidity,… in 10 rooms based on room_id names… The principle is the same…

Different devices (hardware/software) have similar output formats, unified names (eg from_device, device_status,…) with corresponding values.

Considering that HA and similar software are multifunctional, I thought there was some kind of addon, integration or something to handle this type of input data…

For MQTT there is, for ZIGBEE there is, for JSON there is apparently no message parser…

In NodeRED this is piece of cake, one node, and done!
JSON messages are filtered by “from_address” to corresponding outputs. Simple.


But in this case I want to use pure HA.

Thx for comment!

What do you mean by “handle”? Is this data coming into HA already? What do you have, and what do you want to do with it?

It’s easy to set up e.g. a template binary sensor that only reads from_address: 35 inputs, but to help further we need to know what form the “input” into HA is. Example rest sensor if the JSON is coming from a URL:

rest:
  - resource: URL
    binary_sensor:
      - name: Switch 35
        state: >
          {% if value_json['from_address'] == 35 %}
            {{ value_json['device_state'] == 'ACTIVE' }}
          {% else %}
            {{ this.state }}
          {% endif %}

That will carry-over the prior state if the from_address is not 35.

I have a device (DIY) that communicates with several other devices.
Let’s call it a transceiver (gateway). Other devices are: EndNode1, EndNode2 and EndNode3.

Communication between the mentioned devices is LoRa and that is not important in this case.

What is important is that the transceiver (gateway) is connected to the serial port (/dev/USB0) and that it sends and receives data to EndNode1/2/3.

The message that comes to the serial port is one of the examples in the first post (depending on which EndNode corresponds).

I want to make 3 entities, each for one EndNode device, so that each one receives the data “device_type” and “device_state” depending on whether the “from_address” in the message is 10, 25 or 35.

Again, how is HA seeing these messages coming in to the serial port? Are they in an existing entity? Or is that what you’re looking for help with?

No entities are created, I need to create them for EndNode1/2/3/n so that each shows “device_type” and “device_state” depending on whether “from_address” is 10, 25 or 35.

The serial port is configured and that part works OK (I have the data).

This is frustratingly slow going…

What do you mean, you “have the data”?

Is it visible in HA or not, and if it is, how? Show us something we can work with!

I don’t know how to better explain that I receive data through the serial port: “I have data”, “I am getting data”, “data is coming”,…

configuration.yaml:

sensor:
  - platform: serial
    baudrate: 115200
    serial_port: /dev/serial/by-id/usb-1a86_USB_Serial-if00-port0
    name: loramagic

to see what is coming to the serial port:

- name: all_from_serial
        state: '{{ states("sensor.loramagic") }}'

Developer tools → STATES:

…or something from the first post (JSON)…

So I “have the data” :wink:
I hope it’s a little clearer now.

That could have meant you see the data by looking at the low-level serial device via the operating system but don’t have it in HA yet…

What you have provided is exactly what I wanted to see. So now make a template binary sensor: you can do this in the UI, under Helpers:

The state template I used is:

{% if (states('sensor.loramagic')|from_json)['from_address'] == '35' %}
  {{ (states('sensor.loramagic')|from_json)['device_state'] == 'ACTIVE' }}
{% else %}
  {{ this.state }}
{% endif %}

That doesn’t do anything with device_type. What are you looking to achieve? A sensor with state equal to device_state and a device_type attribute?

Yes, I want a sensor with state equal to device_state and a device_type attribute!

OK, you’ll have to do that in YAML:

template:
  - binary_sensor:
      - name: "EndNode 3"
        state: >
          {% if (states('sensor.loramagic')|from_json)['from_address'] == '35' %}
            {{ (states('sensor.loramagic')|from_json)['device_state'] == 'ACTIVE' }}
          {% else %}
            {{ this.state }}
          {% endif %}
        attributes:
          device_type: >
            {% if (states('sensor.loramagic')|from_json)['from_address'] == '35' %}
              {{ (states('sensor.loramagic')|from_json)['device_type'] }}
            {% else %}
              {{ this.attributes['device_type'] }}
            {% endif %}

…and likewise for the others.

Will try tomorrow. THX!

1 Like

I made a small change (state is the value from “device_state”, and the attribute(for now) is removed, and everything works as it should! Excellent!!

The final looks like this:

template:
  - sensor:
      - name: "lora garage"
        unique_id: loragarage
        state: >
          {% if (states('sensor.loramagic')|from_json)['from_address'] == '35' %}
          {{ (states('sensor.loramagic')|from_json)['device_state'] }}
          {% else %}
          {{ this.state }}
          {% endif %}

Also as cover:

cover:
  - platform: template
    covers:
      door2_test:
        device_class: garage
        friendly_name: "door2_test"
        unique_id: door2_test
        value_template: >
          {% if (states('sensor.loramagic')|from_json)['from_address'] == '35' %}
          {{ (states('sensor.loramagic')|from_json)['device_state'] }}
          {% else %}
          {{ this.state }}
          {% endif %}

        open_cover:
          service: shell_command.garage_pulse
        close_cover:
          service: shell_command.garage_pulse
        stop_cover:
          service: shell_command.garage_query

shell_command:
  garage_pulse: echo -e '10,POWER1=P''\r' > /dev/ttyUSB0
  garage_query: echo -e '10,DOOR=?''\r' > /dev/ttyUSB0

Thank you very much for the very precise instructions, they are quite enough for a beginner like me!

And another question for setting the icon for the first example (template):

{% if (states('sensor.loramagic')|from_json)['from_address'] == '35' %}
{{ (states('sensor.loramagic')|from_json)['device_state'] }}
{% set icon_state = (states('sensor.loramagic')|from_json)['device_state'] %}
{% else %}
{{ this.state }}
{% endif %}
icon: >
  {% if icon_state == "OPEN" %}
    mdi:garage-open
  {% else %}
    mdi:garage
  {% endif %}

This works in Developer tools->TEMPLATE but does not change the icon on the dashboard?

icon_state won’t survive into the icon: section — you’ll need to re-create it.

Okay, I managed to steal 5 minutes and make some progress:

icon: >
  {% set from = (states('sensor.loramagic')|from_json)['from_address'] %}
  {% set state = (states('sensor.loramagic')|from_json)['device_state'] %}
  {% if from == "35" and state == "OPEN" %} 
    mdi:garage-open
  {% elif from == "35" and state == "CLOSED" %}
    mdi:garage
  {% else %}
    mdi:help
  {% endif %}    

Icon for OPEN and CLOSED work OK(“from” = 35), but problem is in

{% else %}

If there is nothing(empty), dashboard return mdi:eye , for above mentionedif/elif conditions.
Is there something like {{ this.state }} but for icon(s) or some other method to keep previous icon value?