nledez/traffic_light_pi_server

View on GitHub
lib/traffic_light_pi_server.rb

Summary

Maintainability
A
55 mins
Test Coverage
require 'sinatra'
require 'sinatra/json'
require 'haml'
if RUBY_PLATFORM == 'arm-linux-eabihf'
  require "wiringpi"
end

class TrafficLightPiServer < Sinatra::Base
  helpers Sinatra::JSON

  def self.init_lights
    unless defined? @@mp3player
      @@mp3player = "mpg123"
    end

    unless defined? @@sound_dir
      @@sound_dir = "#{File.dirname(__FILE__)}/sounds"
    end

    @@pi_enabled = nil
    if RUBY_PLATFORM == 'arm-linux-eabihf'
      @@io = WiringPi::GPIO.new
      @@pi_enabled = true
    end

    @@lines = Hash.new
    @@line_map.each_key do |line|
      @@lines[line] = Hash.new
      @@line_map[line].each_key do |light|
        if @@pi_enabled
          pin = get_pin(line, light)
          @@io.mode(pin, OUTPUT)
          @@lines[line][light] = @@io.read(pin)
        else
          @@lines[line][light] = 0
        end
      end
    end
  end

  # A custom 500
  error do
    haml :'500'
  end

  # A custom 404
  not_found do
    haml :'404'
  end

  # Put a default page
  get '/' do
    @lines = @@lines
    @line_map = @@line_map
    haml :index, :format => :html5
  end

  get '/lines' do
    json @@lines
  end

  get '/play/:sound' do
    sound = params[:sound]
    mp3 = "#{@@sound_dir}/#{sound}.mp3"
    if File.exist? mp3
      pid = fork{ exec @@mp3player, '-q', mp3 }
      "Played with pid: #{pid}"
    else
      status 404
    end
  end

  # Reset all lines
  post '/reset' do
    @@line_map.each do |line, lights|
      reset_line(line)
    end
    json @@lines
  end

  # Reset one line
  post '/:line/reset' do
    line = params[:line].to_sym
    reset_line(line)
    json @@lines[line]
  end

  # Get current status for one light/color in one line
  get '/:line/:light' do
    line = params[:line].to_sym
    light = params[:light].to_sym

    #pin = get_pin(line, light)
    #state = @@lines[line][light.to_sym]
    json @@lines[line][light.to_sym]
  end

  # Set status of one light/light in one line
  post '/:line/:light/:state' do
    line = params[:line].to_sym
    light = params[:light].to_sym
    state = params[:state].to_i

    if state != 0 && state != 1
      raise "Bad state value (must be 0 or 1)"
    end

    write_light(line, light, state).to_s
  end

  def get_pin(line, light)
    @@line_map[line][light]
  end

  def write_light(line, light, state)
    pin = get_pin(line, light)
    if @@pi_enabled
      @@io.write(pin, state)
      @@lines[line][light] = @@io.read(pin)
    else
      @@lines[line][light] = state
    end
  end

  def reset_line(line)
    @@line_map[line].each do |light, pin|
      write_light(line, light, 0)
    end
    write_light(line, :green, 1)
  end
end