Remote controlled Home Automation using Sinatra, Ruby and the LightwaveRF Wifi box

In the last post I created a Ruby Gem to communicate with the LightwaveRF Wifi Link Box. The next step was getting that gem into a web server so that I could send commands to the LightwaveRF box over HTTP. The eventual aim was to get this deployed on a RaspberryPi so that it could act as an always-on webserver to control any of the devices in the house.

The obvious choice for a lightweight and simple webserver in Ruby is Sinatra. The following code was all it took to get things started:

class App < Sinatra::Base
  def initialize
    super
    @lightwave = LightwaveRF.new
  end

  get "/" do
    body "Usage: turn items on or off: /[on|off]/:room/:device to dim /dim/:room/:device/:level. Level should be between 0 and 100."
  end

  get "/:room/:device/:action/?:level?" do |room, device, action, level|
    return [422, "Level required for dim"] if action == "dim" && !level
    case action
    when /on/i
      @lightwave.turn_on(room, device)
    when /off/i
      @lightwave.turn_off(room, device)
    when /dim/i
      puts level
      @lightwave.dim(room, device, level.to_i)
    else
      return [422, "Unknown action #{action}"]
    end
    body "Room #{room} Device #{device} #{action}#{" to #{level}%" if level}."
  end
end

The code starts off by creating an instance of the LightwaveRF gem. Then you can just call the root page on the server to see the interface. Then you can use the following to turn on room 1, device 2.

http://localhost:9292/on/1/2

or to Dim room 2, device 3 to 50% you could use:

http://localhost:9292/dim/2/3/50

Don’t forget you’ll need to register the device first by calling LightwaveRF.new.register from the computer that’s running the webserver.

If you’re not familiar with Ruby the following should help you get setup in the terminal assuming that you have ruby installed:

git clone git@github.com:scsmith/lightwaverf-sinatra.git
cd lightwaverf-sinatra
bundle install --path ./vendor/bundle
bundle exec ruby -e "require 'lightwave_rf'; LightwaveRF.new.register; puts 'Done'"
bundle exec rackup -p 9292

This will register the device and start the server running on port 9292 (the default for sinatra). You can then call http://localhost:9292/ like above to start using the server.

Advertisements

Home automation with Ruby using the LightwaveRF Wifi Link box

I recently got to play with the LightwaveRF Wifi Link box (http://www.lightwaverf.com/). They’re becoming fairly common in the UK with companies like screwfix selling them. You can get a range of devices to pair with the box including lights, plug sockets and even PIR sensors. We plugged things in, got a lightbulb paired up and had a play. It’s pretty cool however the next step was writing our own software to control it. Who doesn’t want to control their house using Ruby?

Unfortunately the LightwaveRF Wifi Link doesn’t come with an API or any obvious way to communicate with it outside the tools that the company provide. I was just about ready to get out wireshark and try to figure out the protocol it was using to communicate however, fortunately someone had already done this.

It turned out talking to the box is pretty simple over UDP. First you have to initialise the conversation and pair the device you want to use to communicate with the Wifi box. You can do that with the following:

socket = UDPSocket.new
socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
socket.send("533,!R1D1F0|", 0, "255.255.255.255", 9760)
socket.close

Once you’ve done this commands are sent in the following format:

"001,!R1D2F1"

Prefix: 001
Room: 1
Device: 2
Function Code: F1

The prefix is a random number between 001 and 099 Function code F0 means turn off, F1 means turn on and to Dim a device you can send FdPXX where XX is a number between 1 and 32, with FdP32 meaning full brightness. So the following code would dim Room 2, Device 3 to 50% brightness:

socket = UDPSocket.new
socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
socket.send("001,!R2D3FdP16|", 0, "255.255.255.255", 9760)
socket.close

To make this easier I’ve published the LightwaveRF Ruby Gem to let you interact with the device from Ruby in a much easier way.

lightwave = LightwaveRF.new

# Initial Registration (Only needs doing once per device)
lightwave.register

# Turn the light on in room 1, device number 1
lightwave.turn_on(1, 1)

# Dim the lights in room 2, device number 3 after turning them on
lightwave.turn_on(2, 3)
lightwave.dim(2, 3, 50)

# Turn off the lights
lightwave.turn_off(1, 1)
lightwave.turn_off(2, 3)

For more details or if you find any other features to add checkout the project on Github. The next step was to add this gem to a small Sinatra webserver, which I’ll post soon.