[webhook] New, very simple binding for listening incomming http requests

Hello,

I have scratched a simple binding for listening to incoming http requests.

What problem does it solve?
There are quite a few devices which are able to perform http requests on a given webhook (like Synology Surveillance Station in rules or some intercoms/ip doorphones like akuvox). Those httprequest cannot be simple utilized in openhab straight away. You could translate it at nginx level from the simple form of http get/post those devices can perform to openhab REST APIs or create a simple server which passes mentioned request to mqtt.
However those methods requires third party software to be involved. With this binding you can expose an url to be called by your devices and handle it in the openhab directly.

How this binding works?
When you create a thing you can configure it with only one parameter - JSON like string. Example

{
  "channels": [
    {
      "key":"action",
      "kind": "STATE",
      "state": "req.parameters.action[0]"
    },{
      "key": "card",
      "kind": "STATE",
      "state": "req.parameters.card[0]"
    }
  ]
}

In this parameter you define channels that will be exposed by the thing. key means the id of the channel. Kind is either STATE or TRIGGER (both are implemented) type of a channel. state is an expression based on apache jexl expression language.

As for now in the expression there is only a simple object req which has only two properties:

  1. parameters - under this property all query parameters and form-encoded post parameters are placed. So you can define in your http requests query params and extract it to channels.
    2 body - unders this property the body of the POST requests is stored. body has two properties text and json. With this you can post a json file to you openhab and use an expression to extract an value from the json and place it into channel. See further examples.

Context for expressions can be enriched with more than one req object in future.

Examples

Handling an card input to my doorphone.
I have configured my doorphone to call following url when someone use the mifare tag on it.

http://oh/httplistener/intercomhook?action=cardaction&card=$card_sn

Then I have configured a thing with following json snippet

{
  "channels": [
    {
      "key":"action",
      "kind": "STATE",
      "state": "req.parameters.action[0]"
    },{
      "key": "card",
      "kind": "STATE",
      "state": "req.parameters.card[0]"
    }
  ]
}

Result:

Extracting posted JSON
Following call

curl -H "Content-Type: application/json" -X POST -d '{"username":"test-username"}' http://localhost:8080/httplistener/af71afd830/

With configured thing:

{
  "channels": [
    {
      "key":"testowy",
      "kind": "STATE",
      "state": "req.parameters.ekologia[0]"
    },{
     "key": "testjson",
     "kind": "STATE",
     "state": "req.body.json.username"
    }
  ]

And result:

That’s all. :slight_smile: Any suggestions are welcomed. I do not call it early alpha or something - I wouldn’t recommend to use it on production (though I have deployed in on my openhab). However maybe some of you would be interested and have some hints how evolve it to a useful binding.

Binaries and a source code is here.

Regards,
Piotr

6 Likes

This is really interesting. I might be missing something, but how do you expose the /httplistener URL? Does the binding do this automatically?

I’m also guessing that this is only available on the local network, and that devices posting to it will also have to be on that network (or on a VPN/reverse proxy). I think that’s worth clarifying before people start getting ideas about exposing their OH servers to the Internet. :wink:

Each thing is exposed under /httplistener/[thindid] url automatically and every call to http://youropenhab/httplistener/thingid/any-further-url-path is redirected to mapping you describe as simple json config.

And yeah, it works only locally on your local openhab - in fact this is based on a servlet deployed on a openhab.

2 Likes