Convert Webhook into multiple Temp Sensors

Below is a sample of what I receive via a webhook from a service for monitoring temperatures. The start of every message is the Gateway message, which I am not interested in at all. However, after the gateway message is multiple temperature sensors and their relative information. I am trying to get each one of these into HA as their own sensor with just the “plotValues” as the sensor value. Side note, there are more that 10 sensors that update at random intervals, so each time I get a payload it varies. One payload will have 4 sensors in it, another with 3, and another with 6, etc. Also, they are not always in the same order… The “sensorName” and “sensorID” will never change. I am at the point that I am basically willing to pay to have this problem resolved. Thank you to anyone who takes the time to read this and respond with any useful information.

{
  "gatewayMessage": {
    "gatewayID": "974112",
    "gatewayName": "Ethernet Gateway 4 - 974112",
    "accountID": "43372",
    "networkID": "71498",
    "messageType": "0",
    "power": "0",
    "batteryLevel": "101",
    "date": "2023-05-19 23:59:48",
    "count": "8",
    "signalStrength": "0",
    "pendingChange": "False"
  },
  "sensorMessages": [
    {
      "sensorID": "746835",
      "sensorName": "Temp Meat Island Center Section",
      "applicationID": "2",
      "networkID": "71498",
      "dataMessageGUID": "ffda6a8a-13f8-4d04-b604-8e39f7ef9434",
      "state": "16",
      "messageDate": "2023-05-19 23:54:55",
      "rawData": "0.2",
      "dataType": "TemperatureData",
      "dataValue": "0.2",
      "plotValues": "32.36",
      "plotLabels": "Fahrenheit",
      "batteryLevel": "100",
      "signalStrength": "85",
      "pendingChange": "True",
      "voltage": "2.94"
    },
    {
      "sensorID": "746754",
      "sensorName": "Temp Two Door End Aisle 3/4",
      "applicationID": "2",
      "networkID": "71498",
      "dataMessageGUID": "3c38fe29-1130-41cf-bd80-6520ff03282a",
      "state": "16",
      "messageDate": "2023-05-19 23:54:56",
      "rawData": "-11.6",
      "dataType": "TemperatureData",
      "dataValue": "-11.6",
      "plotValues": "11.12",
      "plotLabels": "Fahrenheit",
      "batteryLevel": "100",
      "signalStrength": "80",
      "pendingChange": "True",
      "voltage": "2.95"
    },
    {
      "sensorID": "860163",
      "sensorName": "Meat Line",
      "applicationID": "2",
      "networkID": "71498",
      "dataMessageGUID": "5ee10847-180e-42ce-8110-441b734eb4e2",
      "state": "16",
      "messageDate": "2023-05-19 23:55:10",
      "rawData": "-3.3",
      "dataType": "TemperatureData",
      "dataValue": "-3.3",
      "plotValues": "26.06",
      "plotLabels": "Fahrenheit",
      "batteryLevel": "100",
      "signalStrength": "80",
      "pendingChange": "True",
      "voltage": "2.96"
    },
    {
      "sensorID": "746823",
      "sensorName": "Temp Walk-in Cooler #5",
      "applicationID": "2",
      "networkID": "71498",
      "dataMessageGUID": "77897983-0c77-4132-9887-62987526dcdb",
      "state": "16",
      "messageDate": "2023-05-19 23:55:30",
      "rawData": "-0.3",
      "dataType": "TemperatureData",
      "dataValue": "-0.3",
      "plotValues": "31.46",
      "plotLabels": "Fahrenheit",
      "batteryLevel": "100",
      "signalStrength": "69",
      "pendingChange": "True",
      "voltage": "2.95"
    },
    {
      "sensorID": "746783",
      "sensorName": "Temp Walk-in Freezer # 1",
      "applicationID": "2",
      "networkID": "71498",
      "dataMessageGUID": "b3a85a61-21bd-470f-a9ef-381728ac7c8f",
      "state": "16",
      "messageDate": "2023-05-19 23:57:30",
      "rawData": "-12.4",
      "dataType": "TemperatureData",
      "dataValue": "-12.4",
      "plotValues": "9.68",
      "plotLabels": "Fahrenheit",
      "batteryLevel": "100",
      "signalStrength": "72",
      "pendingChange": "True",
      "voltage": "2.94"
    },
    {
      "sensorID": "746764",
      "sensorName": "Temp Walk-in Freezer #4",
      "applicationID": "2",
      "networkID": "71498",
      "dataMessageGUID": "ca67b5e4-7b93-43f0-9e02-a2f673bcf895",
      "state": "16",
      "messageDate": "2023-05-19 23:58:22",
      "rawData": "-2.1",
      "dataType": "TemperatureData",
      "dataValue": "-2.1",
      "plotValues": "28.22",
      "plotLabels": "Fahrenheit",
      "batteryLevel": "100",
      "signalStrength": "70",
      "pendingChange": "True",
      "voltage": "2.96"
    },
    {
      "sensorID": "860183",
      "sensorName": "Cutting Room",
      "applicationID": "2",
      "networkID": "71498",
      "dataMessageGUID": "be121ba0-63e0-4ae9-ac6e-7c50e1eb5db9",
      "state": "16",
      "messageDate": "2023-05-19 23:59:13",
      "rawData": "10",
      "dataType": "TemperatureData",
      "dataValue": "10",
      "plotValues": "50",
      "plotLabels": "Fahrenheit",
      "batteryLevel": "100",
      "signalStrength": "46",
      "pendingChange": "True",
      "voltage": "3.01"
    },
    {
      "sensorID": "746827",
      "sensorName": "Temp Walk-in Cooler #7",
      "applicationID": "2",
      "networkID": "71498",
      "dataMessageGUID": "996b3a01-5990-46bc-8965-c64eb0c1a206",
      "state": "16",
      "messageDate": "2023-05-19 23:59:42",
      "rawData": "-0.8",
      "dataType": "TemperatureData",
      "dataValue": "-0.8",
      "plotValues": "30.56",
      "plotLabels": "Fahrenheit",
      "batteryLevel": "100",
      "signalStrength": "76",
      "pendingChange": "True",
      "voltage": "2.96"
    }
  ]
}

I’m going to assume you’ve got one entity which has “sensorMessages” as an attribute. So then you create a template sensor for, say “Meat Line” (id 860163), along the lines of:

{% set value = stateattr('sensor.my_webhook', 'sensorMessages')
        | selectattr("sensorID", "eq", "860163") | map(attribute="plotValues")
        | first | default("") %}
{{ value if value != "" else states("sensor.meat_line") }}

This assumes your template sensor has an “entity_id” of “sensor.meat_line”, such that if the value is “” (ie. not in this set of data) the old value is used. You could combine this into just one by using the previous state as the default, but I think it’s a bit easier to read this way.

Suggestion:

  • Store the webhook payload in an event
  • Create one/many triggered template sensor that would trigger on the event, and that extract the actual values from the event data

See WTH can't input helpers be read only in UI - #7 by CentralCommand

The event_data would be "{{ trigger.json }}"

Thank you for helping me. I do not have an entity with “sensorMessages” as an attribute. At this point, all I’ve managed to do is get the webhook pointed to my Home Assistant instance. All sensors that I’ve attempted to setup have not worked so I erased them all and just posted the payload hoping someone could help. I will share whatever I need to so that I can get this working. If you don’t mind, could you explain or provide the necessary code for me to create an entity with that attribute? I wish I understood code more… I’m willing and quick to learn. If you can help me get one done, I will do the rest. Again, thank you for any time you devote to my issue.

I’ve got the event data working. It’s extracting the data that I can’t get. Based on the code michaelblight shared, it seems to try to do what I wanted which is search for a specific ID or Name and report the value for that object. I don’t understand JSON at all… I’ve made several attempts and even tried ChatGPT… The issue I was having is that the payload changes order, not every sensor is in each payload and I didn’t understand how to perform the search function, or any function for that matter, to find the object and report its temperature value for a given name or ID. Thank you for helping me by the way.

Full solution (with Michael’s bits)
EDIT: Multiple sensors

automations.yaml

- id: webhook_test_state_temp
  alias: Webhook test set temperature
  trigger:
  - platform: webhook
    webhook_id: set_temp_sensors
    allowed_methods:
    - POST
    local_only: true
  action:
  - alias: Update Meat Line sensor
    event: set_meat_line_sensor
    event_data:
      state: '{{ trigger.json["sensorMessages"] | selectattr("sensorID", "eq", "860163") | map(attribute="plotValues") | first | default("") }}'
  - alias: "Update Walk-in Cooler #7"
    event: set_walk_in_cooler_7_sensor
    event_data:
      state: '{{ trigger.json["sensorMessages"] | selectattr("sensorID", "eq", "746827") | map(attribute="plotValues") | first | default("") }}'
  mode: single

Template sensor

- trigger:
  - platform: event
    event_type: set_meat_line_sensor
  sensor:
  - name: Webhook Meat Line
    state: "{{ trigger.event.data.state }}"

- trigger:
  - platform: event
    event_type: set_walk_in_cooler_7_sensor
  sensor:
  - name: "Webhook Walk-in Cooler #7"
    state: "{{ trigger.event.data.state }}"

Curl test

curl --location 'https://ha-test.spax.pm/api/webhook/set_temp_sensors' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer `<my_token>' \
--data '{
  "gatewayMessage": {
    "gatewayID": "974112",
[...]
    {
      "sensorID": "860163",
      "sensorName": "Meat Line",
      "applicationID": "2",
      "networkID": "71498",
      "dataMessageGUID": "5ee10847-180e-42ce-8110-441b734eb4e2",
      "state": "16",
      "messageDate": "2023-05-19 23:55:10",
      "rawData": "-3.3",
      "dataType": "TemperatureData",
      "dataValue": "-3.3",
      "plotValues": "26.06",
      "plotLabels": "Fahrenheit",
      "batteryLevel": "100",
      "signalStrength": "80",
      "pendingChange": "True",
      "voltage": "2.96"
    },
[...]

outcome

Thank you so much for doing all of that for me! I have a better understanding of what exactly is going on and how to proceed in the future examining what you have written. Sometimes, studying the final written code helps me better understand how to get there. Gives me that “aha” moment and the light bulb turns on. Again, thank you and I hope you have a wonderful day!

Resurrecting this thread as I have the exact same iMonnit webhook. I’m wondering how you got around the fact that not every sensor is included in each webhook? I am finding my sensors go to blank each time there is a webhook trigger that they’re not included in. This is what my sensor looks like:

In the automation, first test (Script Syntax - Home Assistant (home-assistant.io)) if the resulting event data is non-empty before sending the event.

if:
  - condition: template
    value_template: '{{ trigger.json["sensorMessages"] | selectattr("sensorID", "eq", "860163") | map(attribute="plotValues") | first | default("") != "" }}'
[...]
1 Like

Amazing! Thank you!