Integrating openHAB and Garmin

As I wrote in my last post on Garmin and smart home control, unfortunately the openHAB REST API is not usable from Garmin devices, since the Garmin Connect IQ SDK does not support the type of POST request needed to send commands to openHAB. But there is an alternative, the Webhook HTTP binding, which allows custom processing of simple GET requests in openHAB, and in this article I will outline how to setup this binding and implement JavaScript logic to enable control from Garmin devices, or any other devices that do not support the type of REST API used by openHAB.

The figure below shows an overview of the solution. On the Garmin device we use the APICall app to call the URL exposed by the Webhook HTTP binding exposes an URL. The call usually goes via the mobile phone (1) and from there either directly to openHAB (2) or via the myopenhab.org cloud service (3). The Webhook binding triggers a JavaScript rule, which issues commands to devices via their bindings (4).

Note on local network access versus cloud: working via the cloud is obviously required if you want the integration to work also when you are outside of your home. If you prefer, you can also use a VPN solution such as Tailscale for remote access. However, there is another reason for using the cloud service that a VPN cannot solve: the Garmin devices support only HTTPS requests to servers with valid certificates, which in most instances the local openHAB server won’t have. With an iOS mobile phone you can use HTTP on the local network or via VPN instead, but with Android mobile phones Garmin supports only HTTPS. Therefore going via the cloud service is the only option if you use Android and do not have a valid certificate for your local server.

To enable control from the Garmin devices, we’ll implement two types of action, one to send a specific command to an openHAB item, and another to toggle the state of an openHAB switch item between ON and OFF. For that we’ll support the following parameters in the GET requests: 

  • action: “sendCommand” or “toggle”. 
  • itemName: the openHAB item that the action shall be performed on. 
  • command: the command to be sent, only applicable to the “sendCommand” action.

We’ll now have a look at the following steps that are needed to implement this solution:

  • Install the Webhook HTTP binding
  • Configure a Webhook thing
  • Setup a rule to process HTTP requests
  • Build the URLs
  • Choose a Garmin app
  • APICall example configuration

So, let’s dive right into the first one:

Install the Webhook HTTP binding

To install the binding, open your openHAB web interface, go to Add-on Store, search for the Webhook HTTP binding and install it:

Configure a Webhook thing

In this section I’ll cover the setup I choose for setting up the thing. For a complete overview of all the capabilities check the binding’s page in the openHAB forum. There is also an interesting discussion thread, but note that it originally covered an older version of the binding, so many of the information in the initial post and earlier in the thread is not valid anymore.

To actually enable the binding, you need to create a thing with a trigger channel that activates a script to process the request. On your openHAB web interface navigate to Administration, Settings, Things and add a new one by choosing the (+) symbol. Next you choose the Webhook HTTP binding and create the thing.

To configure the thing you need to edit its code, where you can program JEXL expressions for defining the HTTP response and channels that are used to pass data to rules or other types of processing. I decided to create only one trigger channel. Because you can only pass one single string from the trigger channel to the rule, I wrote a JEXL expression that puts all data from the request into one JSON string. As alternative you could create multiple data channels, each holding a different value. But that is more effort, and I am also worried about thread-safety, i.e. what happens if a new request comes in and overwrites the content of a data channel while the previous request is still being processed. The figure below shows how data from an incoming request is passed on by the trigger channel in JSON format:

And now a few screenshots of the thing setup. You can download the YAML code for the thing including the JEXL expression. Note that the JSON string generated by the JEXL also contains request method and body content, which we do not need, but I wanted to create a generic implementation that also supports future use cases.

Create the new thing with the Webhook HTTP binding …

… open it …

… and navigate to Code to setup the trigger channel.

The configuration shown in the previous screenshot gives us two channels. One shows the time of the last request for informational purposes, and the second is a trigger channel that can now be linked to a rule.

Setup a rule to process HTTP requests

Next we’ll setup a rule that processes the incoming requests. We start by creating a new rule, triggered by the trigger channel we created in the previous section. Then as action, we add an inline script, for which you can download my JavaScript code here. The script parses the JSON data passed in from the JEXL in the thing configuration and then acts based on the parameters. The two screenshots below show the rule:

The rule …

… and the JavaScript embedded as inline script action.

Build the URLs

Now with the processing in place, we can start making calls to test what we implemented. To build the URL, you need the name or IP address of your openHAB server, the 10-digit alphanumeric number from your thing UID and the name of the switch item that should be toggled. With that you build the URL as follows:

http://your_openhab_server:8080/webhook/your_thing_id?action=toggle&itemName=your_item

If you’d like to send a specific command, for example for blinds to open, the URL looks like this:

http://your_openhab_server:8080/webhook/your_thing_id?action=sendCommand&itemName=your_item&command=your_command

Only if you have a valid certificate, you can also use HTTPS:

http://your_openhab_server:8443/webhook/your_thing_id?action=toggle&itemName=your_item

If you would like to use the myopenhab.org cloud service, your openHAB needs to have the Cloud Connector installed. You can then use the following URL, sending your myopenhab.org username and password via basic authentication.

https://username:password@home.myopenhab.org/webhook/your_thing_id?action=toggle&itemName=your_item

Note that Garmin does not support the username and password in the URL, instead you need to send it base64-encoded in the header of the request. From the Garmin apps introduced in this article, only APICall can do this. See the configuration example further below for more information.

You can test these URLs in your browser, or via a tool like Postman.

Choose a Garmin app

My previous article on Garmin smart home control lists a few applications that can be used to send HTTP requests from Garmin devices, particularly APICall, MyHomeControl, Web Request and Simple Web Request. I choose APICall because it is well documented and the only one that was able to issue the POST requests needed for the Shelly cloud service. However, all four applications can work with the local Webhook interface to openHAB introduced in this article. 

Both APICall and MyHomeControl can configure multiple devices and actions. MyHomeControl has a bit of a nicer user interface but APICall is more powerful and better documented and supported. For example, APICall can issue calls via WiFi if no Bluetooth connection to a phone is available, which MyHomeControl cannot. Also APICall works on Garmin cycling computers, while MyHomeControl only runs on watches. And only APICall supports the basic authentication in the request header required to make requests via the myopenhab.org cloud service.

Web Request and Simple Web Request are much simpler, only able to issue configure one single request without the basic authentication for the cloud service.

Below some screenshots from APICall and MyHomeControl user interfaces on my Epix Pro Gen 2:

The APICall user interface is a bit more generic, which may be due to the fact that it needs to work on watches and cycling computers.

On the watch, the MyHomeControl user interface looks a bit nicer.

So, while APICall is the most powerful of the bunch, if you can live with its limitations MyHomeControl is a bit more visually pleasing and Web Request and Simple Web Request will do their job if a single request is all you need.

APICall example configuration

Below an example JSON configuration for an action in APICall, via the cloud service. 

{deviceName:”Study”,deviceIcon:62,actionName:”Toggle”,actionIcon:65,method:”GET”,url:”https://home.myopenhab.org/webhook/your_thing_id?action=toggle&itemName=your_item”,headers:”{\”Authorization\”:\”Basic your_base64_auth\”}”}

Replace your_thing_id, your_item and your_base64_auth with the appropriate values. For your_base64_auth, you take “username:password” for myopenhab.org and encode it with this service. For example for “myuser:mypass”, your_base64_auth would be “bXl1c2VyOm15cGFzcw==”.

So, with my thing id of “d1097152a4”, item name “Light_OG_AO_Schreibtisch_Switch” and “myuser:mypass” for authentication, the configuration looks like this:

{deviceName:”Study”,deviceIcon:62,actionName:”Toggle”,actionIcon:65,method:”GET”,url:”https://home.myopenhab.org/webhook/d1097152a4?action=toggle&itemName=Light_OG_AO_Schreibtisch_Switch”,headers:”{\”Authorization\”:\”Basic bXl1c2VyOm15cGFzcw==\”}”}

Conclusion

While the Shelly integration described in the previous article worked well for our car gates, most of our other devices are on a legacy BTicino bus, which is integrated with openHAB and can now be triggered from Garmin as well, which opens up new handy ways of controlling our home. Although it took some time and tinkering to implement, I am quite happy with how the solution turned out, and hope you’ll find it useful as well. If you have any questions, as always, feel free to contact me.