traffic_light_controller 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- traffic_light_controller (0.0.3)
4
+ traffic_light_controller (0.0.5)
5
5
  arduino
6
6
  hashie
7
7
  json
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'traffic_light_controller'
3
- TrafficLightController::CLI.new
3
+ TrafficLightController::CLI.run
@@ -1,7 +1,102 @@
1
1
  module TrafficLightController
2
2
  class CLI
3
+ class << self
4
+ def run
5
+ cli = self.new
6
+ cli.process_command_line_options
7
+ cli.run
8
+ end
9
+ end
10
+
3
11
  def initialize
4
- TrafficLightController::Server.new.work
12
+ @server = Server.new
13
+ end
14
+
15
+ def process_command_line_options
16
+ @options = {}
17
+
18
+ GetoptLong.new(*options_possible).each do |opt, arg|
19
+ case opt
20
+ when '--help'
21
+ show_help_and_exit
22
+ when '--version'
23
+ puts version_info
24
+ exit
25
+ end
26
+ end
27
+ end
28
+
29
+ def run
30
+ server.work
31
+ end
32
+
33
+ private
34
+
35
+ attr_reader :server
36
+
37
+ def options_possible
38
+ [
39
+ ['--help', '-h', GetoptLong::NO_ARGUMENT],
40
+ ['--version', '-V', GetoptLong::NO_ARGUMENT],
41
+ ]
42
+ end
43
+
44
+ def show_help_and_exit
45
+ STDOUT.puts help_info
46
+ exit
47
+ end
48
+
49
+ def help_info
50
+ <<-EOH
51
+ Usage: #{prog_name} [options]
52
+ #{short_hand_options}
53
+
54
+ Options:
55
+ #{option_details}
56
+ #{version_info}
57
+ EOH
58
+ end
59
+
60
+ def prog_name
61
+ File.basename($0)
62
+ end
63
+
64
+ def short_hand_options
65
+ "[#{options_possible.map{ |o| short_hand_option(o)}.join('], [')}]"
66
+ end
67
+
68
+ def short_hand_option(option)
69
+ if option[2] == GetoptLong::REQUIRED_ARGUMENT
70
+ [option[0], option[1]].join('|') << " argument"
71
+ else
72
+ [option[0], option[1]].join('|')
73
+ end
74
+ end
75
+
76
+ def option_details
77
+ <<-EOO
78
+ #{options_possible.map{ |o| expand_option(o) }.join("\n")}
79
+ EOO
80
+ end
81
+
82
+ def version_info
83
+ <<-EOV
84
+ traffic_light_controller (#{version_number})
85
+ https://github.com/jcmuller/traffic_light_controller
86
+ (c) 2012 Juan C. Muller
87
+ EOV
88
+ end
89
+
90
+ def version_number
91
+ VERSION
92
+ end
93
+
94
+ def longest_width
95
+ @max_width ||= options_possible.map{ |o| o[0] }.max{ |a, b| a.length <=> b.length }.length
96
+ end
97
+
98
+ def expand_option(option)
99
+ sprintf(" %-#{longest_width + 6}s %s", option.first(2).join(', '), option[3])
5
100
  end
6
101
  end
7
102
  end
@@ -5,6 +5,7 @@ module TrafficLightController
5
5
  Thread.abort_on_exception = true
6
6
  @config = Config.new
7
7
  @server = TCPServer.new(config.server.address, config.server.port)
8
+ @current_path = ""
8
9
  rescue Errno::EADDRINUSE
9
10
  address_in_use_error(config.server)
10
11
  rescue Errno::EADDRNOTAVAIL, SocketError
@@ -19,28 +20,43 @@ module TrafficLightController
19
20
 
20
21
  private
21
22
 
22
- attr_reader :server, :config, :board
23
+ attr_reader :server, :config, :board, :current_path
23
24
 
24
25
  def start_thread_and_do_work
25
- Thread.start(server.accept) do |client|
26
- work_with_client(client)
26
+ Thread.start(server.accept) do |request|
27
+ accept_request(request)
27
28
  end
28
29
  end
29
30
 
30
- def work_with_client(client)
31
- puts "work_with_client"
32
- process_path(process_request(client))
31
+ def accept_request(request)
32
+ process_request(request)
33
33
  rescue => e
34
- puts "Got #{e.class}: #{e}!"
34
+ STDERR.puts "Got #{e.class}: #{e}!
35
+
36
+ #{e.backtrace.join($/)}"
35
37
  ensure
36
- client.close
38
+ request.close
37
39
  end
38
40
 
39
- def process_request(client)
40
- puts "process_request"
41
- path = nil
41
+ def process_request(request)
42
+ path = path_from_request(request)
42
43
 
43
- while(line = client.readline) do
44
+ if config.arduino.lights.has_key?(path)
45
+ if path != current_path
46
+ @current_path = path
47
+ change_pins(path)
48
+ respond_200(request, path)
49
+ else
50
+ respond_304(request, path)
51
+ end
52
+ else
53
+ respond_404(request, path)
54
+ end
55
+ end
56
+
57
+ def path_from_request(request)
58
+ path = ""
59
+ while(line = request.readline) do
44
60
  break if line == "\r\n"
45
61
  if match = line.match(%r{GET /+(?<path>\w*) HTTP/1\.})
46
62
  path = match[:path]
@@ -50,28 +66,28 @@ module TrafficLightController
50
66
  path
51
67
  end
52
68
 
53
- def process_path(path)
54
- puts "process_path"
55
- if config.arduino.lights.has_key?(path)
56
- change_pins(path)
57
- client.print "HTTP/1.1 200 OK\r\nContent-type:text/plain\r\n\r\n"
58
- client.puts path
59
- else
60
- client.print "HTTP/1.1 404 Not Found\r\nContent-type:text/plain\r\n\r\n"
61
- client.puts "The requested path doesn't exist"
62
- end
63
- end
64
-
65
69
  def change_pins(path)
66
- puts "change_pins"
67
70
  init_board
68
71
  board.turnOff
69
72
  board.setHigh(config.arduino.lights[path]) unless path == "off"
70
73
  board.close
71
74
  end
72
75
 
76
+ def respond_200(request, path)
77
+ request.print "HTTP/1.1 200 OK\r\nContent-type:text/plain\r\n\r\n"
78
+ request.puts path
79
+ end
80
+
81
+ def respond_304(request, path)
82
+ request.puts "HTTP/1.1 304 Not Modified\r\nContent-type:text/plain\r\n\r\n"
83
+ end
84
+
85
+ def respond_404(request, path)
86
+ request.print "HTTP/1.1 404 Not Found\r\nContent-type:text/plain\r\n\r\n"
87
+ request.puts "The requested path doesn't exist"
88
+ end
89
+
73
90
  def init_board
74
- puts "board"
75
91
  @board = Arduino.new(config.arduino.port)
76
92
  rescue Errno::ENOENT
77
93
  STDERR.puts "The port #{config.arduino.port} doesn't exist"
@@ -1,3 +1,3 @@
1
1
  module TrafficLightController
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -1,5 +1,6 @@
1
1
  require "rubygems"
2
2
  require "arduino"
3
+ require "getoptlong"
3
4
  require "hashie"
4
5
  require "socket"
5
6
  require "yaml"
@@ -8,5 +9,5 @@ module TrafficLightController
8
9
  autoload :Config, "traffic_light_controller/config"
9
10
  autoload :CLI, "traffic_light_controller/cli"
10
11
  autoload :Server, "traffic_light_controller/server"
11
- autoload :VERION, "traffic_light_controller/version"
12
+ autoload :VERSION, "traffic_light_controller/version"
12
13
  end
@@ -1,12 +1,42 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe TrafficLightController::CLI do
4
- describe "#work" do
4
+ let(:config) { mock }
5
+ let(:server) { mock }
6
+
7
+ before do
8
+ TrafficLightController::Config.stub(:new).and_return(config)
9
+ TrafficLightController::Server.stub(:new).and_return(server)
10
+
11
+ config.stub_chain(:server, :address).and_return("127.0.0.1")
12
+ config.stub_chain(:server, :port).and_return(5678)
13
+ end
14
+
15
+ describe ".run" do
5
16
  it "should initialize server and call work on it" do
6
17
  server = mock
7
18
  TrafficLightController::Server.should_receive(:new).and_return(server)
8
19
  server.should_receive(:work)
9
- described_class.new
20
+ described_class.run
21
+ end
22
+ end
23
+
24
+ describe "show_help_and_exit" do
25
+ it "should show help" do
26
+ STDOUT.stub(:puts)
27
+ subject.should_receive(:help_info)
28
+ expect{ subject.send(:show_help_and_exit) }.to raise_error SystemExit
29
+ end
30
+ end
31
+
32
+ describe "#help_info" do
33
+ it "should return the nice string" do
34
+ subject.should_receive(:prog_name)
35
+ subject.should_receive(:short_hand_options)
36
+ subject.should_receive(:option_details)
37
+ subject.should_receive(:version_info)
38
+
39
+ subject.send(:help_info)
10
40
  end
11
41
  end
12
42
  end
@@ -69,28 +69,25 @@ describe TrafficLightController::Server do
69
69
  describe "#start_thread_and_do_work" do
70
70
  it "should start a thread" do
71
71
  Thread.should_receive(:start).and_yield(client)
72
- subject.should_receive(:work_with_client).with(client)
72
+ subject.should_receive(:accept_request).with(client)
73
73
  subject.send(:start_thread_and_do_work)
74
74
  end
75
75
  end
76
76
 
77
- describe "#work_with_client" do
77
+ describe "#accept_request" do
78
78
  it "should call process path" do
79
79
  subject.should_receive(:process_request).with(client).and_return(:processed)
80
- subject.should_receive(:process_path).with(:processed)
81
80
  client.should_receive(:close)
82
81
 
83
- subject.send(:work_with_client, client)
82
+ subject.send(:accept_request, client)
84
83
  end
85
84
 
86
- it "should rescue from all exceptions and log them to STDOUT" do
85
+ it "should rescue from all exceptions and log them to STDERR" do
87
86
  subject.should_receive(:process_request).and_raise RuntimeError
88
-
89
- STDOUT.should_receive(:puts).with("Got RuntimeError: RuntimeError!")
90
-
87
+ STDERR.should_receive(:puts)
91
88
  client.should_receive(:close)
92
89
 
93
- subject.send(:work_with_client, client)
90
+ subject.send(:accept_request, client)
94
91
  end
95
92
  end
96
93
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: traffic_light_controller
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: