toxuin / alarmserver

IP Camera Alarm Server to MQTT
MIT License
145 stars 34 forks source link

webhooks headers (feature request) #9

Closed alitaker closed 2 years ago

alitaker commented 2 years ago

Hi, thank you for this nice alarmserver. I was wondering if you could add the parameter of an "Authorization: Bearer" header in the webhooks (or a generic header parameter). Many services require some headers and in this way, one may directly call Home Assistant REST APIs without calling MQTT, if needed.

You may have a look here on the REST API page.

From the go http client page it seems pretty straightforward (just use webhooks.client.Header.Add,() but it would need to change the configuration package and the SendMessage func... and I'm not very confortable with GO.

Thank you.

toxuin commented 2 years ago

I'm definitely interested in implementing this feature and to make webhooks more usable in general and I'm glad you brought that up. Thank you!

I have recently moved and all my cameras are not connected yet so there is going to be some delay with me implementing it. However, I have started writing some code already; just warning against expecting it being merged into main any time soon 😄

alitaker commented 2 years ago

That's great news! I started myself trying to build the code to be able to change it and test it, but it seems some dependencies have changed and I get the following messages:

~/go/src/github.com/toxuin/alarmserver$ go build
../../spf13/viper/internal/encoding/hcl/codec.go:8:2: cannot find package "github.com/hashicorp/hcl/hcl/printer" in any of:
        /usr/src/github.com/hashicorp/hcl/hcl/printer (from $GOROOT)
        /home/marco/go/src/github.com/hashicorp/hcl/hcl/printer (from $GOPATH)
../../../goftp.io/server/v2/compat.go:17:2: cannot find package "goftp.io/server/core" in any of:
        /usr/src/goftp.io/server/core (from $GOROOT)
        /home/marco/go/src/goftp.io/server/core (from $GOPATH)
../../../goftp.io/server/v2/compat.go:18:2: cannot find package "goftp.io/server/driver/file" in any of:
        /usr/src/goftp.io/server/driver/file (from $GOROOT)
        /home/marco/go/src/goftp.io/server/driver/file (from $GOPATH)
../../../goftp.io/server/v2/compat.go:19:2: cannot find package "goftp.io/server/driver/minio" in any of:
        /usr/src/goftp.io/server/driver/minio (from $GOROOT)
        /home/marco/go/src/goftp.io/server/driver/minio (from $GOPATH)

Any suggestions?

toxuin commented 2 years ago

You can see the way it's built in the Dockerfile:

go get -d ./... && CGO_ENABLED=0 go build -ldflags="-w -s" -o ./out/alarmserver I hope that helps!

alitaker commented 2 years ago

Yep, thank you! I had to:

export GO111MODULE="on"

and then run:

go get -d ./... && CGO_ENABLED=1 go build -gccgoflags="-w -s" -o ./out/alarmserver

with CGO_ENABLED=1, or I would get errors like:

/go/pkg/mod/golang.org/x/sys@v0.0.0-20200323222414-85ca7c5b95cd/unix/gccgo.go:50: undefined reference to `gccgoRealSyscallNoError'

Now it's building and running as expected. Will post here any news...

toxuin commented 2 years ago

I've worked a bit on this and it seems to work fine in my synthetic setup.

@alitaker are you able to test this new implementation? All my cameras are still in boxes somewhere -__-

You have to either build the branch webhook-headers or use docker image tagged toxuin/alarmserver:webhook-headers.

Please be my QA for this! 🙏 I'm hopeful you can test it at least a little so I can make a new release with this feature.

I appreciate your help! ^_^

alitaker commented 2 years ago

Yes, I have a couple of cameras I can test it on. Will let you know as soon as the setup is up and running.

alitaker commented 2 years ago

Hi @toxuin , just to report... I still have to debug it, but I keep getting:

Got no response from https://<my_ha_server>:<my_ha_port>/api/states/binary_sensor.dev001

Maybe it's a docker thing, will check when I have more time

BTW, my config now is:

hisilicon:
  enabled: true
  port: 15003

webhooks:
  enabled: true
  urls:
    - "https://<my_ha_server>:<my_ha_port>/api/states/binary_sensor.dev001"
  headers:
    - "Authorization: Bearer <my_ha_token>"
toxuin commented 2 years ago

Most likely this is due to connectivity within docker and its ports (container/host ports, etc).

However, this exact use case would not work currently, as this particular endpoint expects a certain schema of the request that alarmserver definitely does not conform to. Here's the link to Home Assistant API docs and it requires there to be a state field which does not exist on the JSON that Alarmserver sends.

There are infinite use cases with webhooks, so just outputting Alarmservers own internal JSON schema would be the most versatile way as it would not require me to write a wrapper for every API in existence, nor would it require users to write some kind of templated config to send webhooks in a specific format.

For your specific use case though - would MQTT integration be not sufficient? Do you run a home assistant without MQTT broker?

alitaker commented 2 years ago

Yes, I am aware of the HA APIs requirements. Actually I started using HA without MQTT and before starting with Alarmserver in GO, I made some modifications to the PHP implementation PhpCameraAlarmGateway (forked here). My fork rewrites the JSON with device_class=motion, state=on|off, custom icon and friendly_name (ready for HA UI) Indeed that would be a very specific webhook implementation, but I guess it's one of the most used, so for me it's worth it.

toxuin commented 2 years ago

Do you use nodered by any chance? You could expose the webhook endpoint and transform the payload in nodered - maybe that would be an option?

toxuin commented 2 years ago

Oops, I've also found a small mistake in your config:

webhooks:
  enabled: true
  urls:
    - "https://<my_ha_server>:<my_ha_port>/api/states/binary_sensor.dev001"
  headers:
    - "Authorization: Bearer <my_ha_token>"

shoud be

webhooks:
  enabled: true
  items:
    - url: "https://<my_ha_server>:<my_ha_port>/api/states/binary_sensor.dev001"
      headers:
        - "Authorization: Bearer <my_ha_token>"

webhooks.urls config key is the "old" implementation and is basically just a shorthand with all the default options for a webhook (POST method, no headers).

alitaker commented 2 years ago

Rigth, thank you: I've changed my config.

I also sorted out the "Got no response from..." error. There were actually two problems:

  1. I needed to specify the FQDN, otherwise I got an SSL certificate error
  2. Since the Docker container is on another IP, I had to enable remote access for my authorized user

Now I get the expected error 400 Bad request (because the JSON payload does not contain the status field).

Will figure out if MQTT or Node Red can be an option. Anyway, would it be ok for you if I try to implement the JSON manipulation for direct HA requests?

toxuin commented 2 years ago

Feel free to! It sounds like it is a viable use case for you at least. I tried to give it a bit of thought and I still could not come up with anything that would be non-HA specific yet flexible enough to work with HA REST API. I am now curious what would you come up with 😄

Seems like this improvement is working as intended with no major bugs discovered, so I am going to merge the #11 and close this as fixed.

@alitaker please, feel free to open another issue if you find any problems with webhooks (or anything else, really). Also, looking forward to see your PR with JSON manipulation 👍

toxuin commented 2 years ago

I was today years old when I discovered there's Webhook trigger in Home Assistant 🤦

I am just mentioning here in case it would be advantageous for your use case @alitaker .

In combination with binary_switch it could be an easy solution to the above problem - no node-red required.

alitaker commented 2 years ago

Yes Webhook triggers seem very useful. I'm currently using the states API to alter a virtual binary sensor in HA, so I can check in the history and see what happened to that sensor (I have other non-virtual binary sensors and this way seems more linear as every detector has its sensor).

The webhook would be a quicker implementation though, because you skip the binary sensor (definition+state change). I'll probably test both ways... as soon as I find some spare time! :sweat_smile: Thanx!