This is the second in a series about the home automation prototype system. The first post is here.
The home automation prototype we’re building in my research lab has an HTTP proxy that translates communication between the in-home devices (DVD player and light dimmer in our example) and KNS. This proxy is running on the local home network and may not have a public IP address or domain name. That causes problems when we want a KRL ruleset to be able to talk directly to the proxy.
I first heard about
localtunnel over a month ago when Twilio announced it. It’s a service that lets you tunnel any port on your local machine to a publicly accessible domain name. The domain name is randomly generated, providing some security by obscurity. This is the perfect solution for letting KNS talk to the local proxy in our system.
There’s still one problem, though. Every time the localtunnel is reestablished, the domain name changes. I could go manually edit the KRL each time that occurs so that it always points to the right place, but that is unreasonable in a production environment.
The KRL The solution is to have the proxy server ping a webhook on the same KRL ruleset every time the server gets a new localtunnel address. Then the ruleset simply keeps that address around in an app variable. Here’s what the KRL looks like for that:
To use it, we simply reference the app variable. These are the functions I mentioned in the last post that handle communication with the proxy server:
The proxy server
The HTTP proxy itself is running Sinatra, so it listens on port 4567 by default. To use
localtunnel, I’d normally just write this:
$ localtunnel 4567
Which spits out something like this:
This localtunnel service is brought to you by Twilio.
Port 4567 is now publicly accessible from http://3pjg.localtunnel.com …
To automate it, however, I need to get that URL programmatically. Parsing the output wouldn’t work, because the
localtunnel instance stays running as long as the tunnel is open. I ultimately decided to fork the repo on Github and add the feature myself. Here’s the original repo, and here’s my fork.
What I added was a function that pings a webhook once the URL has been obtained from the
localtunnel web service. Take a look at the diff.
Now all I have to do is call
LocalTunnel::Tunnel.new() and pass the webhook URL as well. Like this:
Every time I start the Sinatra server, I also run this script to open the
localtunnel and notify the KRL ruleset of the change. No manual updating, and everything works great.
In a production system, we’d want to authenticate everything so that a rogue server can’t come in and redirect our traffic to a different place. But for the prototype, this is sufficient.
Note: If you want to follow the whole project, you can find it on Github.