ir_ptz 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fuci.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,42 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ir_ptz (0.0.1)
5
+ arduino_ir_remote (~> 0.1.1)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ arduino_ir_remote (0.1.1)
11
+ args_parser (>= 0.2.0)
12
+ event_emitter
13
+ serialport
14
+ args_parser (0.2.0)
15
+ bourne (1.5.0)
16
+ mocha (>= 0.13.2, < 0.15)
17
+ diff-lcs (1.2.4)
18
+ event_emitter (0.2.5)
19
+ metaclass (0.0.1)
20
+ mocha (0.14.0)
21
+ metaclass (~> 0.0.1)
22
+ rake (10.1.0)
23
+ rspec (2.14.1)
24
+ rspec-core (~> 2.14.0)
25
+ rspec-expectations (~> 2.14.0)
26
+ rspec-mocks (~> 2.14.0)
27
+ rspec-core (2.14.5)
28
+ rspec-expectations (2.14.3)
29
+ diff-lcs (>= 1.1.3, < 2.0)
30
+ rspec-mocks (2.14.3)
31
+ serialport (1.1.0)
32
+
33
+ PLATFORMS
34
+ ruby
35
+
36
+ DEPENDENCIES
37
+ bourne
38
+ bundler (~> 1.3)
39
+ ir_ptz!
40
+ mocha
41
+ rake
42
+ rspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Will Mernagh
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ ## IR PTZ
2
+
3
+ CLI to controle a Pan, Tilt, and Zoom Camera by InfraRed via an Arduino. This
4
+ is just a wrapper around
5
+ [arduino_ir_remote](https://github.com/shokai/arduino_ir_remote) that adds the following:
6
+
7
+ - cli to replay recorded codes
8
+ - ability to record new codes
9
+
10
+ ## Requirements
11
+
12
+ * Arduino Uno
13
+ * [IR Shield](http://store.linksprite.com/linksprite-infrared-shield-for-arduino/) or IR LED and an IR Reviever
14
+ * USB cable (printer cabel)
15
+
16
+ ## Hardware Installation
17
+
18
+ * Connect the shield to the Arduino
19
+ * Connect arduino via USB to yoru computer
20
+
21
+ Note if you are not using a shield the IR LED should be connected to PIN 3 and
22
+ the IR Receiver should be connected to PIN 11
23
+
24
+ ## Software installation
25
+
26
+ Install this gem
27
+
28
+ $ gem install ir_ptz
29
+
30
+ You will need to install the Arduino SDK and load the sketch from this gem. To
31
+ find the sketch run the following:
32
+
33
+ $ gem contents ir_ptz | grep arduino.ino
34
+ /PATH_TO_GEMS/1.9.1/gems/ir_ptz-x.x.x/arduino/arduino.ino
35
+
36
+ Then in the SDK open the output from above (e.g. `/PATH_TO_GEMS/1.9.1/gems/ir_ptz-x.x.x/arduino/arduino.ino`)
37
+
38
+ ## Still to do
39
+
40
+ Have writing to the Arduino not stop processing incoming key presses. Basically
41
+ I will buffer the input in one thread and write out the buffer in the other I
42
+ think.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ RSpec::Core::RakeTask.new('spec')
4
+
5
+ # If you want to make this the default task
6
+ task :default => :spec
@@ -0,0 +1,118 @@
1
+ #define IR_DATA_SIZE 768
2
+ byte ir_data[IR_DATA_SIZE];
3
+ unsigned int ir_index;
4
+ #define PIN_LED 13
5
+ #define PIN_IR_IN 11
6
+ #define PIN_IR_OUT 3
7
+
8
+ void setup(){
9
+ Serial.begin(57600);
10
+ pinMode(PIN_IR_IN, INPUT);
11
+ pinMode(PIN_IR_OUT, OUTPUT);
12
+ pinMode(PIN_LED, OUTPUT);
13
+ }
14
+
15
+ unsigned int analog_count = 0;
16
+ void loop(){
17
+ if(Serial.available()){
18
+ char recv = Serial.read();
19
+ process_input(recv);
20
+ }
21
+ else{
22
+ if(analog_count < 1){
23
+ for(byte i = 0; i < 6; i++){
24
+ Serial.print("ANALOG");
25
+ Serial.println(i);
26
+ Serial.println(analogRead(i));
27
+ }
28
+ }
29
+ analog_count += 1;
30
+ if(analog_count > 65534) analog_count = 0;
31
+ }
32
+ }
33
+
34
+ void ir_read(byte ir_pin){
35
+ unsigned int i, j;
36
+ for(i = 0; i < IR_DATA_SIZE; i++){
37
+ ir_data[i] = 0;
38
+ }
39
+ unsigned long now, last, start_at;
40
+ boolean stat;
41
+ start_at = micros();
42
+ while(stat = digitalRead(ir_pin)){
43
+ if(micros() - start_at > 2500000) return;
44
+ }
45
+ start_at = last = micros();
46
+ for(i = 0; i < IR_DATA_SIZE; i++){
47
+ for(j = 0; ; j++){
48
+ if(stat != digitalRead(ir_pin)) break;
49
+ if(j > 65534) return;
50
+ }
51
+ now = micros();
52
+ ir_data[i] = (now - last)/100;
53
+ last = now;
54
+ stat = !stat;
55
+ }
56
+ }
57
+
58
+ void ir_print(){
59
+ unsigned int i;
60
+ for(i = 0; i < IR_DATA_SIZE; i++){
61
+ Serial.print(ir_data[i]);
62
+ if(ir_data[i] < 1) break;
63
+ Serial.print(",");
64
+ }
65
+ Serial.println();
66
+ }
67
+
68
+ void ir_write(byte ir_pin){
69
+ unsigned int i;
70
+ unsigned long interval_sum, start_at;
71
+ interval_sum = 0;
72
+ start_at = micros();
73
+ for(i = 0; i < IR_DATA_SIZE; i++){
74
+ if(ir_data[i] < 1) break;
75
+ interval_sum += ir_data[i] * 100;
76
+ if(i % 2 == 0){
77
+ while(micros() - start_at < interval_sum){
78
+ digitalWrite(ir_pin, true);
79
+ delayMicroseconds(6);
80
+ digitalWrite(ir_pin, false);
81
+ delayMicroseconds(8);
82
+ }
83
+ }
84
+ else{
85
+ while(micros() - start_at < interval_sum);
86
+ }
87
+ }
88
+ }
89
+
90
+ void process_input(char input){
91
+ if(input == 'r'){
92
+ digitalWrite(PIN_LED, true);
93
+ ir_read(PIN_IR_IN);
94
+ Serial.println("READ");
95
+ ir_print();
96
+ digitalWrite(PIN_LED, false);
97
+ }
98
+ else if(input == 'w'){
99
+ for(ir_index = 0; ir_index < IR_DATA_SIZE; ir_index++){
100
+ ir_data[ir_index] = 0;
101
+ }
102
+ ir_index = 0;
103
+ }
104
+ else if(input == ','){
105
+ if(ir_index < IR_DATA_SIZE) ir_index += 1;
106
+ }
107
+ else if(input >= '0' && '9' >= input){
108
+ ir_data[ir_index] = ir_data[ir_index]*10 + (input - '0');
109
+ }
110
+ else if(input == 'W'){
111
+ digitalWrite(PIN_LED, true);
112
+ ir_write(PIN_IR_OUT);
113
+ ir_index = 0;
114
+ Serial.println("WRITE");
115
+ ir_print();
116
+ digitalWrite(PIN_LED, false);
117
+ }
118
+ }
data/bin/ir_ptz ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ require 'fileutils'
3
+
4
+ DATA_FILE = ENV["IR_DATA_FILE"] || File.expand_path('.ir_remote.yml', ENV['HOME'])
5
+ unless File.exists?(DATA_FILE)
6
+ default_file = File.join(File.dirname(File.expand_path(__FILE__)), '../data/ir_remote.yml')
7
+ FileUtils.cp default_file, DATA_FILE
8
+ end
9
+
10
+ require 'ir_ptz'
11
+ require 'ir_ptz/command_line'
12
+
13
+ IrPtz::CommandLine.new.run
@@ -0,0 +1,16 @@
1
+ ---
2
+ actions:
3
+ tilt_up: '89,44,5,5,5,16,5,5,5,5,5,5,5,5,5,5,5,5,5,16,5,5,5,16,5,16,5,16,5,16,5,16,5,16,5,5,5,5,5,16,5,5,5,16,5,16,5,5,5,16,5,16,5,16,5,5,5,16,5,5,5,5,5,16,5,5,5,143,89,22,5,192,89,22,5,192,89,22,5,192,89,22,5,192,89,22,5,0'
4
+ tilt_down: '90,44,6,4,6,16,6,4,6,4,6,4,6,4,6,4,6,4,6,16,6,4,6,16,6,16,6,16,6,16,6,16,6,16,6,4,6,4,6,16,6,16,6,16,6,16,6,4,6,16,6,16,6,16,6,4,6,4,6,4,6,4,6,16,6,4,6,142,90,21,6,0'
5
+ pan_right: '90,44,6,4,6,16,6,4,6,4,6,4,6,4,6,4,6,4,6,16,6,4,6,16,6,16,6,16,6,16,6,16,6,16,6,4,6,4,6,16,6,16,6,16,6,16,6,16,6,16,6,16,6,16,6,4,6,4,6,4,6,4,6,4,6,4,6,142,90,21,6,0'
6
+ pan_left: '90,44,6,4,6,16,6,4,6,4,6,4,6,4,6,4,6,4,6,16,6,4,6,16,6,16,6,16,6,16,6,16,6,16,6,4,6,4,6,16,6,4,6,16,6,16,6,16,6,16,6,16,6,16,6,4,6,16,6,4,6,4,6,4,6,4,6,0'
7
+ zoom_in: '90,44,6,4,6,16,6,4,6,4,6,4,6,4,6,4,6,4,6,16,6,4,6,16,6,16,6,16,6,16,6,16,6,16,6,4,6,16,6,4,6,4,6,4,6,16,6,4,6,16,6,16,6,4,6,16,6,16,6,16,6,4,6,16,6,4,6,142,90,21,6,0'
8
+ zoom_out: '89,44,5,5,5,16,5,5,5,5,5,5,5,5,5,5,5,5,5,16,5,5,5,16,5,16,5,16,5,16,5,16,5,16,5,5,5,16,5,5,5,5,5,5,5,16,5,16,5,16,5,16,5,5,5,16,5,16,5,16,5,5,5,5,5,5,5,143,89,22,5,0'
9
+ action_mappings:
10
+ k: tilt_up
11
+ j: tilt_down
12
+ l: pan_right
13
+ h: pan_left
14
+ i: zoom_in
15
+ o: zoom_out
16
+ device_path: /dev/tty.usbmodem401321
data/ir_ptz.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ir_ptz/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ir_ptz"
8
+ spec.version = IrPtz::VERSION
9
+ spec.authors = ["Will Mernagh"]
10
+ spec.email = ["wmernagh@gmail.com"]
11
+ spec.description = %q{CLI to control a Pan Tilt Zoom Camera by InfraRed via an Arduino}
12
+ spec.summary = %q{see homepage}
13
+ spec.homepage = "https://github.com/wmernagh/ir_ptz"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split("\n")
17
+ spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "arduino_ir_remote", "~> 0.1.1"
22
+ spec.add_development_dependency "bundler", "~> 1.3"
23
+ spec.add_development_dependency "rake"
24
+ spec.add_development_dependency "rspec"
25
+ spec.add_development_dependency "mocha"
26
+ spec.add_development_dependency "bourne"
27
+ end
data/lib/ir_ptz.rb ADDED
@@ -0,0 +1,43 @@
1
+ require 'bundler/setup'
2
+
3
+ module IrPtz
4
+ class << self
5
+ attr_accessor :configuration
6
+ end
7
+
8
+ # Configure IrPtz in ~/.ir_ptz_config.rb to override the defaults
9
+ #
10
+ # @example
11
+ # IrPtz.configure do |config|
12
+ # config.device_path = '/dev/tty.usbmodem9999'
13
+ # config.in_key = 'a'
14
+ # config.out_key = 's'
15
+ # end
16
+ def self.configure
17
+ yield(configuration) if block_given?
18
+ end
19
+
20
+ def self.configuration
21
+ @configuration ||= Configuration.new
22
+ end
23
+
24
+ class Configuration
25
+ attr_accessor :escape_key, :help_key, :record_key, :actions, :action_mappings
26
+ attr_accessor :device_path
27
+
28
+ def initialize
29
+ self.escape_key = 'e'
30
+ self.help_key = '?'
31
+ self.record_key = 'r'
32
+ self.action_mappings = ArduinoIrRemote::DATA['action_mappings']
33
+ self.actions = ArduinoIrRemote::DATA['actions']
34
+ self.device_path = ArduinoIrRemote::DATA['device_path']
35
+ end
36
+ end
37
+ end
38
+
39
+ require "ir_ptz/version"
40
+ require 'arduino_ir_remote'
41
+ require "ir_ptz/ir_remote"
42
+ require "ir_ptz/ir_command_recorder"
43
+ require "ir_ptz/command_line"
@@ -0,0 +1,62 @@
1
+ require 'io/console'
2
+
3
+ module IrPtz
4
+ class CommandLine
5
+ attr_reader :ir_remote
6
+
7
+ def initialize
8
+ # ensure_configured
9
+ @ir_remote = IrRemote.instance
10
+ end
11
+
12
+ def run
13
+ print_instructions
14
+
15
+ while key = STDIN.getch
16
+ case key
17
+ when config.escape_key
18
+ puts 'Goodbye!'
19
+ break
20
+ when config.help_key
21
+ print_instructions
22
+ when config.record_key
23
+ ir_command_recorder.record.save
24
+ else
25
+ if action = action(key)
26
+ ir_remote.send action(key)
27
+ else
28
+ print_instructions
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def ir_command_recorder
37
+ IrCommandRecorder
38
+ end
39
+
40
+ def action(key)
41
+ config.action_mappings[key]
42
+ end
43
+
44
+ def config
45
+ IrPtz.configuration
46
+ end
47
+
48
+ def print_instructions
49
+ puts instructions
50
+ end
51
+
52
+ def instructions
53
+ title = "\nThe following key commands are available:\n"
54
+ exit_text = "\t'#{config.escape_key}' to exit."
55
+ help_text = "\t'#{config.help_key}' for help"
56
+ record_text = "\t'#{config.record_key}' record a new command"
57
+ custom_text = config.action_mappings.map { |k, v| "\t'#{k}' to #{v}" }
58
+ instructions = [title, exit_text, help_text, record_text] + custom_text
59
+ instructions.join "\n"
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,63 @@
1
+ require 'io/console'
2
+
3
+ module IrPtz
4
+ class IrCommandRecorder
5
+ Command = Struct.new(:title, :key, :action_code) do
6
+ def save
7
+ ArduinoIrRemote::DATA['action_mappings'][key] = title
8
+ ArduinoIrRemote::DATA['actions'][title] = action_code
9
+ ArduinoIrRemote::DATA.save
10
+ puts "#{title} saved!"
11
+ end
12
+ end
13
+
14
+ def self.record
15
+ command = nil
16
+ title = get_title
17
+ key = get_key
18
+ code = get_ir_code
19
+
20
+ @command = Command.new(title, key, code)
21
+ end
22
+
23
+ private
24
+ class BlankException < Exception; end
25
+ NON_WHITESPACE_REGEXP = %r![^\s#{[0x3000].pack("U")}]!
26
+
27
+ def self.blank?(string)
28
+ res = string !~ NON_WHITESPACE_REGEXP
29
+ end
30
+
31
+ def self.get_title
32
+ print 'Enter command title: '
33
+ title = gets.chomp
34
+
35
+ if IrPtz.configuration.actions.has_key? title
36
+ puts %Q{overwrite "#{title}" ?}
37
+ print "[Y/n] > "
38
+ return nil unless gets.strip =~ /Y/
39
+ end
40
+
41
+ blank?(title) ? get_title : title
42
+ end
43
+
44
+ def self.get_key
45
+ puts 'Enter the key to be used to send the command: '
46
+ key = getch
47
+
48
+ if IrPtz.configuration.action_mappings.has_key? key
49
+ puts %Q{overwrite "#{args[:read]}" ?}
50
+ print "[Y/n] > "
51
+ return nil unless gets.strip =~ /Y/
52
+ end
53
+
54
+ blank?(key) ? get_key : key
55
+ end
56
+
57
+ def self.get_ir_code
58
+ ir_code = IrRemote.instance.read_code
59
+ blank?(ir_code) ? get_ir_code : ir_code
60
+ end
61
+ private_class_method :get_ir_code
62
+ end
63
+ end
@@ -0,0 +1,40 @@
1
+ require 'arduino_ir_remote'
2
+ require 'singleton'
3
+
4
+ module IrPtz
5
+ class IrRemote
6
+ include Singleton
7
+
8
+ IrPtz.configuration.actions.keys.each do |action|
9
+ define_method(action) do
10
+ if ir_code = IrPtz.configuration.actions[action]
11
+ ir.write ir_code
12
+ end
13
+ end
14
+ end
15
+
16
+ def read_code
17
+ data = nil
18
+ end_of_read = nil
19
+
20
+ ir.read do |ir_data|
21
+ data = ir_data
22
+ end_of_read = true
23
+ end
24
+
25
+ puts "reading.."
26
+ ir.wait { sleep 1; break if end_of_read }
27
+ puts "finished reading!"
28
+
29
+ data
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :ir
35
+
36
+ def initialize
37
+ @ir = ArduinoIrRemote.connect IrPtz.configuration.device_path
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ module IrPtz
2
+ VERSION = "0.0.1"
3
+ end
data/spec/helpers.rb ADDED
@@ -0,0 +1,16 @@
1
+ module Helpers
2
+ def expect_key_delegates_to_remote(key, command)
3
+ escape_key = IrPtz.configuration.escape_key
4
+ STDIN.stubs(:getch).returns key, escape_key
5
+
6
+ ir_remote = mock
7
+ IrPtz::IrRemote.stubs(:new).returns ir_remote
8
+ ir_remote.stubs(command)
9
+
10
+ cli = IrPtz::CommandLine.new
11
+ cli.stubs(:puts)
12
+ cli.run
13
+
14
+ # expect(ir_remote).to have_received(command)
15
+ end
16
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+ require 'ir_ptz'
3
+ require 'ir_ptz/ir_remote'
4
+
5
+ describe IrPtz::CommandLine do
6
+ context 'non remote commands' do
7
+ let(:escape_key) { IrPtz.configuration.escape_key }
8
+ let(:record_key) { IrPtz.configuration.record_key }
9
+ let(:bad_key) { '.' }
10
+ let(:getch_stub) { STDIN.stubs(:getch) }
11
+ subject(:cli) { IrPtz::CommandLine.new }
12
+
13
+ describe '#run' do
14
+ before { cli.stubs(:puts) }
15
+
16
+ it 'prints the instructions' do
17
+ instructions = cli.send(:instructions)
18
+ getch_stub.returns escape_key
19
+
20
+ cli.run
21
+
22
+ expect(cli).to have_received(:puts).with(instructions)
23
+ end
24
+
25
+ it 'listens for the escape key and exits upon receipt' do
26
+ getch_stub.returns escape_key
27
+
28
+ cli.run
29
+
30
+ expect(cli).to have_received(:puts).with('Goodbye!')
31
+ end
32
+
33
+ it 'prints the instruction when a bad key is pressed' do
34
+ instructions = cli.send(:instructions)
35
+ getch_stub.returns bad_key, escape_key
36
+
37
+ cli.run
38
+
39
+ # twice - once at the start and once for the bad key
40
+ expect(cli).to have_received(:puts).with(instructions).twice
41
+ end
42
+
43
+ it 'loops until the escape key is pressed' do
44
+ instructions = cli.send(:instructions)
45
+ getch_stub.returns bad_key, bad_key, escape_key
46
+
47
+ cli.run
48
+
49
+ # trice - once at the start and once for each bad key press
50
+ expect(cli).to have_received(:puts).with(instructions).times(3)
51
+ end
52
+
53
+ it 'passes record_new_command to IRCommandRecorder' do
54
+ IrPtz::IrCommandRecorder.stubs(:record).returns(mock(:save))
55
+ getch_stub.returns record_key, escape_key
56
+
57
+ cli.run
58
+
59
+ expect(IrPtz::IrCommandRecorder).to have_received(:record)
60
+ end
61
+ end
62
+
63
+ context 'remote specific commands' do
64
+ IrPtz.configuration.action_mappings.keys.each do |key|
65
+ it 'passes commands to IR Remote' do
66
+ IrPtz::IrRemote.instance.stubs(:read_code)
67
+
68
+ expect_key_delegates_to_remote key, IrPtz.configuration.action_mappings[key]
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+ require 'ir_ptz'
3
+
4
+ describe IrPtz::IrCommandRecorder do
5
+ describe '#record' do
6
+ subject(:recorder) { IrPtz::IrCommandRecorder }
7
+ let(:title) { "xxx\n" }
8
+ let(:confirmation) { '' }
9
+
10
+
11
+ before do
12
+ recorder.stubs(:puts)
13
+ recorder.stubs(:print)
14
+ recorder.stubs(:getch).returns("x")
15
+ recorder.stubs(:gets).returns(title, confirmation)
16
+ end
17
+
18
+ describe '.get_title' do
19
+ it 'asks the user to enter the command title' do
20
+ recorder.get_title
21
+ expect(recorder).to have_received(:print).with 'Enter command title: '
22
+ end
23
+
24
+ it 'reads in the command title' do
25
+ expect(recorder.get_title).to eql 'xxx'
26
+ end
27
+
28
+ context 'title already exists' do
29
+ let(:title) { "zoom_in\n" }
30
+ let(:confirmation) { 'Y' }
31
+
32
+ it 'asks if you want to override it' do
33
+ recorder.get_title
34
+ expect(recorder).to have_received(:puts).with 'overwrite "zoom_in" ?'
35
+ expect(recorder).to have_received(:print).with '[Y/n] > '
36
+ end
37
+
38
+ it 'returns the key if you enter Y' do
39
+ expect(recorder.get_title).to eql title.chomp
40
+ end
41
+
42
+ context 'you do not enter Y' do
43
+ let(:confirmation) { 'r' }
44
+
45
+ it 'returns nil' do
46
+ expect(recorder.get_title).to eql nil
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ it 'creates a new command' do
53
+ IrPtz::IrRemote.stubs(:instance).returns mock(read_code: '93,44')
54
+ ir_command = IrPtz::IrCommandRecorder::Command.new('xxx', 'x', '93,44')
55
+ expect(recorder.record).to eql ir_command
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+ require 'ir_ptz'
3
+ require 'arduino_ir_remote'
4
+
5
+ describe IrPtz::IrRemote do
6
+ subject(:ir) { IrPtz::IrRemote.instance }
7
+ let(:arduino_ir) { mock }
8
+
9
+ before do
10
+ ir.stubs(:ir).returns arduino_ir
11
+ end
12
+
13
+ # concrete example
14
+ describe 'zoom_in' do
15
+ before do
16
+ arduino_ir.stubs(:write)
17
+ ArduinoIrRemote::DATA['actions']['zoom_in'] = 'some value'
18
+ end
19
+
20
+ it 'sends the zoom in signal to the board' do
21
+ ir.zoom_in
22
+ expect(arduino_ir).to have_received(:write).with 'some value'
23
+ end
24
+ end
25
+
26
+ # dynamic example
27
+ ArduinoIrRemote::DATA['actions'].keys.each do |action|
28
+ describe 'actions' do
29
+ before do
30
+ ArduinoIrRemote::DATA['actions'][action] = 'some value'
31
+ arduino_ir.stubs(:write)
32
+ end
33
+
34
+ it 'can send a defined singnal to the board' do
35
+ ir.send(action)
36
+ expect(arduino_ir).to have_received(:write).with 'some value'
37
+ end
38
+ end
39
+ end
40
+
41
+ describe '#read_code' do
42
+ it 'returns the read in signal'
43
+ end
44
+ end
@@ -0,0 +1,11 @@
1
+ require 'mocha/api'
2
+ require 'bourne'
3
+ require 'helpers'
4
+
5
+ data_file = File.join(File.dirname(File.expand_path(__FILE__)), '../data/ir_remote.yml')
6
+ ENV["IR_DATA_FILE"] = data_file
7
+
8
+ RSpec.configure do |config|
9
+ config.mock_with :mocha
10
+ config.include Helpers
11
+ end
metadata ADDED
@@ -0,0 +1,168 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ir_ptz
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Will Mernagh
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-10-29 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: arduino_ir_remote
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.1.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 0.1.1
30
+ - !ruby/object:Gem::Dependency
31
+ name: bundler
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '1.3'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '1.3'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: mocha
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: bourne
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ description: CLI to control a Pan Tilt Zoom Camera by InfraRed via an Arduino
111
+ email:
112
+ - wmernagh@gmail.com
113
+ executables:
114
+ - ir_ptz
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - .gitignore
119
+ - Gemfile
120
+ - Gemfile.lock
121
+ - LICENSE
122
+ - README.md
123
+ - Rakefile
124
+ - arduino/arduino.ino
125
+ - bin/ir_ptz
126
+ - data/ir_remote.yml
127
+ - ir_ptz.gemspec
128
+ - lib/ir_ptz.rb
129
+ - lib/ir_ptz/command_line.rb
130
+ - lib/ir_ptz/ir_command_recorder.rb
131
+ - lib/ir_ptz/ir_remote.rb
132
+ - lib/ir_ptz/version.rb
133
+ - spec/helpers.rb
134
+ - spec/ir_ptz/command_line_spec.rb
135
+ - spec/ir_ptz/ir_command_recorder_spec.rb
136
+ - spec/ir_ptz/ir_remote_spec.rb
137
+ - spec/spec_helper.rb
138
+ homepage: https://github.com/wmernagh/ir_ptz
139
+ licenses:
140
+ - MIT
141
+ post_install_message:
142
+ rdoc_options: []
143
+ require_paths:
144
+ - lib
145
+ required_ruby_version: !ruby/object:Gem::Requirement
146
+ none: false
147
+ requirements:
148
+ - - ! '>='
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ required_rubygems_version: !ruby/object:Gem::Requirement
152
+ none: false
153
+ requirements:
154
+ - - ! '>='
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ requirements: []
158
+ rubyforge_project:
159
+ rubygems_version: 1.8.23
160
+ signing_key:
161
+ specification_version: 3
162
+ summary: see homepage
163
+ test_files:
164
+ - spec/helpers.rb
165
+ - spec/ir_ptz/command_line_spec.rb
166
+ - spec/ir_ptz/ir_command_recorder_spec.rb
167
+ - spec/ir_ptz/ir_remote_spec.rb
168
+ - spec/spec_helper.rb