Webhook trigger automation

Hello,

I’m using SynoAI (with DeepstackAI) to filter motion triggers in my front garden. This works well but now I like to extract the identified objects to fine tune the automations. With a webhook push I receive the following data (verified through https://webhook.site):

--29ee862b-1a9d-4b6a-a20d-1f3bae1b9812
Content-Type: application/json; charset=utf-8
Content-Disposition: form-data

["car","car"]
--29ee862b-1a9d-4b6a-a20d-1f3bae1b9812--

Which is correct because there are two cars in the camera view. When other objects are detected, the string changes accordingly.

Is there a way to extract this info?

I’ve seen examples using trigger.json.<field> but as per above example, there is no field identifier.

Yes. The list supplied by the URL is accessible directly from trigger.json itself.

If you wish, you can experiment with it using this example:

## Webhook experiment
- alias: Webhook Experiment
  trigger:
  - platform: webhook
    webhook_id: your_webhook_id_goes_here
  action:
  - service: notify.persistent_notification
    data:
      title: Webhook Experiment
      message: >
        Length: {{ trigger.json | count }}
        {%- for i in trigger.json %}
          {{ i }}
        {%- endfor -%}

Here’s a screenshot of the resulting notification when I post similar data (using ["car", "person"]):

Screenshot from 2021-10-04 15-48-47

If you want the value of the first item in the received list, you can reference it using an index number of zero trigger.json[0] (second item’ index number is one trigger.json[1] and so on). However, you said the number of items can vary so you first have to know how many items are in the list before you attempt to reference any item by its index number. If you attempt to get trigger.json[2] but it doesn’t exist, it will cause an error.

How do you want the automation to handle the items in the list?

Thanks so much for your help and explanation! I would not have figured that out myself.

I will play with this tomorrow and report back my results.

My plan is to set specific light scenes when a car arrives or when a person arrives. Additionally, I also like to scan for cats (and dogs) to activate the sprinklers.

However, as you already pointed out, the changing list of objects may become an issue. The camera is pointing at the driveway. depending who’s home or coming home, there can be a mix of 1 or 2 cars with 1 or 4 persons. And I actually don’t know how the list will be sorted either. I will have to test that. The things is that Deepstack will report any static object in the picture once motion was detected. So a car that was parked all day will be reported together with the cat that just entered the driveway.

BTW, you can test the automation using the curl command so you don’t have to wait for Deepstack to report actual data (there’s an example in the documentation for Webhook Trigger). That’s how I tested it (I don’t have Deepstack).

So what exactly do you plan to do with what it reports?

Thanks for that tip. That will be very useful when I want to test different scenario’s.

For now I have 3 scenarios in mind.

  1. If a car comes home and it’s dark, light scenario 1 gets activated
  2. If a person comes home and it’s dark, light scenario 2 gets activated
  3. If a cat or dog gets on my driveway, sprinklers are activated

Since the string length is undefined, maybe a solution would be to just look at the whole string and prioritise the possible actions?

Thus, if person is part of the list, light scenario 2 will be activated. If only car is found in the list, light scenario 1 is activated. If cat is in the list (and not a person), the sprinklers are turned on.

How do you intend to handle the situation you mentioned where a car is parked on the driveway? The data will always include “car” (and it’s simply parked so you don’t want the lights to be turned on after dark).

That’s where I decided to run 2 different containers with SynoAI. One is triggered by motion and the other one is only triggered by line crossing. So only when something is entering my driveway the specific light scene will be activated because that script will send out the webhook for it.

I’ve been testing your example but I’m having difficulties. HAS is reporting an error in the log when I send the webhook.

Error processing webhook line_crossing_driveway

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/webhook/__init__.py", line 106, in async_handle_webhook
    response = await webhook["handler"](hass, webhook_id, request)
  File "/usr/src/homeassistant/homeassistant/components/push/camera.py", line 76, in handle_webhook
    data = dict(await request.post())
  File "/usr/local/lib/python3.9/site-packages/aiohttp/web_request.py", line 649, in post
    assert field.name is not None
AssertionError

I can change some parameters in SynoAI that sends the webhook like:

  "Method": "POST/PUT/PATCH",
  "Field": "image",
  "SendImage": true/fasle,
  "SendTypes": true/false

and I am getting mixed results if I look at the data received on webhook.site.

For my purpose (object identity) the following setup:

  "Method": "PUT",
  "Field": "image",
  "SendImage": false,
  "SendTypes": true

Gives me this on the webhook.site which should be good for my purpose:

--a23a3fa7-a620-461b-87c5-acf8bbad6e3e
Content-Type: application/json; charset=utf-8
Content-Disposition: form-data
["car"]
--a23a3fa7-a620-461b-87c5-acf8bbad6e3e--

Nevertheless, HAS returns the above error. In fact, it always returns the same error, no matter what the webhook sends.

Your original question has been answered and proven to work on my system.

Begin your tests by first confirming it works when you call the webhook using the curl command. Once you have established it works, proceed to testing it with SynoAI. If it fails, then you know where the fault lies.

Hi @123,

After a short detour fixing some other elements, I picked up this one up again.

After fixing SSL certificate issues on all sides of the communication, I got a few steps further but now I’m stuck.

I tested my webhook with cURL which works well as you can see in the screenshot below:

image

But whenever I invoke the SynoAI script to sent a webhook, I get an error:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/webhook/__init__.py", line 105, in async_handle_webhook
    response = await webhook["handler"](hass, webhook_id, request)
  File "/usr/src/homeassistant/homeassistant/components/webhook/trigger.py", line 30, in _handle_webhook
    result["data"] = await request.post()
  File "/usr/local/lib/python3.9/site-packages/aiohttp/web_request.py", line 649, in post
    assert field.name is not None
AssertionError

After doing several test with cURL and webhook.site, I’m pretty sure it is because the script is including (what I think is) the Content-Type header in the message.

--83a9b3c4-a879-47e4-b803-11bbbef8f3f3
Content-Type: application/json; charset=utf-8
Content-Disposition: form-data

["car","person"]
--83a9b3c4-a879-47e4-b803-11bbbef8f3f3--

and not just the data fields:

["car","person"]

It looks like that the python library web_request.py does not process this well. Close to where web_request.py exits with an error, there is a comment in the code mentioning about the possible existence of this header.

                # Note that according to RFC 7578, the Content-Type header
                # is optional, even for files, so we can't assume it's
                # present.
                # https://tools.ietf.org/html/rfc7578#section-4.4

Can you confirm you did a cURL POST (or PUT) with only the data ie

curl -X PUT -H "Content-Type: application/json" -d '["car", "person"]' --insecure https://homeassistant:8123/api/webhook/line_crossing_driveway

or

`curl -X PUT -d '["car", "person"]'  --insecure https://homeassistant:8123/api/webhook/line_crossing_driveway`  

I’m to much of noob to get into the phyton coding but if you confirm your test method, I could try my luck in the web_request.py github repository

I’m pretty certain that there is no form data. You are posting raw JSON to Home Assistant, so the Content-Disposition header should not be there? The only important header here is:

Content-type: application/json

That’s what tells Home Assistant how to decode it, if it is expecting Form Data, then it is expecting actual form fields (which may themselves contain JSON) which are clearly not present.

Hi Andrew,

Thanks for your help!

Just to make sure I understand you correctly. If the webhook message sent by the script would look as below it will work?

--83a9b3c4-a879-47e4-b803-11bbbef8f3f3
Content-Type: application/json; charset=utf-8

["car","person"]
--83a9b3c4-a879-47e4-b803-11bbbef8f3f3--

Yes ish,
I’m not sure what or where the --83a9b3c4-a879-47e4-b803-11bbbef8f3f3 is coming from, that is form data boundary data, which is not necessary for pure JSON data.