hwping 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a6cbddb5d50553a985d48cda712b992ea667ede9
4
+ data.tar.gz: 72840576bfc2f86a92414f573f957ccdb040b4aa
5
+ SHA512:
6
+ metadata.gz: bbd0ea2f0c0f574e2d144601184c3c93c9f2bdd9bff8f85951164418ca2fce61be5a06441225545288d3cb725b9a3468d40d42d1d43f434f9fa60426959e4dce
7
+ data.tar.gz: af2ce63c355ff50cee63a95f92f60c786eb15b6e449339d5ab99ba6fdc5937f8e4996a6c46e8bad70b95a076e609a16a67c45a5a857b1733160f2fc7a349476d
data/bin/hwping ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'yaml'
5
+ require 'hwping'
6
+
7
+ # Parse arguments
8
+ options = {}
9
+ OptionParser.new do |opts|
10
+ opts.version = HWPing::VERSION
11
+ opts.program_name = HWPing::APP_NAME
12
+ opts.banner = 'Usage: hwping [options]'
13
+ opts.on('-c', '--config-file file.yml', "Specify which configuration file you want to use instead of the default config.yml") do |v|
14
+ options[:config] = v
15
+ end
16
+ end.parse!
17
+
18
+ # Open the configuration
19
+ file = options.fetch(:config, HWPing::CONFIG_FILE)
20
+ config = YAML.load_file(file)
21
+
22
+ # Run the application
23
+ app = HWPing::HWPing.new(config)
24
+ app.start
25
+
26
+ # Stop the bot and save the configuration file
27
+ at_exit do
28
+ app.stop
29
+ File.open(file, 'w') do |f|
30
+ YAML.dump(app.config, f)
31
+ end
32
+ end
data/lib/hwping/bot.rb ADDED
@@ -0,0 +1,67 @@
1
+ require 'cinch'
2
+
3
+ module HWPing
4
+ class Bot
5
+
6
+ MESSAGES = {
7
+ :unauthorized => "Sorry, you're unauthorized to use this bot!",
8
+ :firing => 'Firing rocket in 5 seconds!',
9
+ :notarget => 'Unknown target!',
10
+ :fire => 'Rocket launch initiated!',
11
+ :reset => 'Launcher set back to default position!',
12
+ :position => 'Current position: %d %d',
13
+ :target_list => 'Available targets: %s',
14
+ :target_get => "Target's position: %d %d",
15
+ :target_del => 'Target successfully deleted!',
16
+ :target_set => "Target's position saved at: %d %d",
17
+ :move => 'Move operation finished!',
18
+ :badcommand => "Unknown command, type 'help' for further information!",
19
+ :help => "Hardware Pinger\n
20
+ Usage in a channel: hwping <target>\n
21
+ Available commands in private:\n
22
+ help\n
23
+ fire\n
24
+ position\n
25
+ up|down|left|right\n
26
+ reset\n
27
+ target list\n
28
+ target set <nick> <right> <up>\n
29
+ target get <nick>\n
30
+ target del <nick>\n"
31
+ }
32
+
33
+ # Initialize a bot and return with its Cinch instance
34
+ def initialize(handler, config = {})
35
+ @nick = config.nick
36
+ @server = config.server
37
+ @port = config.port
38
+ @channels = config.channels.map { |m| "\##{m}"}
39
+ @handler = handler
40
+ return setup_bot()
41
+ end
42
+
43
+ private
44
+ def setup_bot
45
+ bot = Cinch::Bot.new do |b|
46
+ configure do |c|
47
+ c.nick = @nick
48
+ c.server = @server
49
+ c.port = @port
50
+ c.channels = @channels
51
+ end
52
+
53
+ # For channel mesages, just reply with the matching message
54
+ on :channel, /^hwping/ do |e|
55
+ r = @handler.channel(e)
56
+ e.reply(MESSAGES[r])
57
+ end
58
+
59
+ # For private messages, build a reply message from the format strinc and the passed variables
60
+ on :private do |e|
61
+ (r, *f) = @handler.message(e)
62
+ e.reply(MESSAGES[r] % f)
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,24 @@
1
+ module HWPing
2
+ class Config
3
+
4
+ attr_reader :server
5
+ attr_reader :port
6
+ attr_reader :nick
7
+ attr_reader :channels
8
+ attr_reader :auth
9
+ attr_accessor :targets
10
+
11
+ def initialize(hash = {})
12
+ @server = hash.fetch(:server, 'irc.freenode.net')
13
+ @port = hash.fetch(:port, 6667)
14
+ @nick = hash.fetch(:nick, 'hwping')
15
+ @channels = hash.fetch(:channels, ['hwping-test'])
16
+ @auth = hash.fetch(:auth , [])
17
+ @targets = hash.fetch(:targets, [])
18
+ end
19
+
20
+ def to_hash
21
+ Hash[instance_variables.map { |name| [name[1..-1], instance_variable_get(name)] }]
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,6 @@
1
+ module HWPing
2
+ VERSION = '0.0.1'
3
+ APP_NAME = 'hwping'
4
+ REPO_URL = 'http://github.com/skateman/hwping'
5
+ CONFIG_FILE = 'config.yml'
6
+ end
@@ -0,0 +1,68 @@
1
+ module HWPing
2
+ class Handler
3
+ # Set up the handler with the configuration
4
+ def initialize(launcher, config)
5
+ @targets = config.targets
6
+ @auth = config.auth
7
+ @nick = config.nick
8
+ @launcher = launcher
9
+ end
10
+
11
+ # If the event happened in a channel, return just with a symbol
12
+ def channel(event)
13
+ if event.message =~ /^hwping,?\s+(.*)\s*$/
14
+ if @auth.include?(event.user.to_s)
15
+ if @targets.include?($1)
16
+ @launcher.point_and_fire(@targets[$1])
17
+ return :firing
18
+ else
19
+ return :notarget
20
+ end
21
+ else
22
+ return :unauthorized
23
+ end
24
+ end
25
+ end
26
+
27
+ # If the event happened in a private window, return with an array
28
+ def private(event)
29
+ if @auth.include?(event.user.to_s)
30
+ case event.message
31
+ when "fire"
32
+ @launcher.fire
33
+ return [:fire]
34
+ when "position"
35
+ return @launcher.position.unshift(:position)
36
+ when "help"
37
+ return [:help]
38
+ when "reset"
39
+ @launcher.reset
40
+ return [:reset]
41
+ when "target list"
42
+ return [:target_list, @targets.keys.join(', ')]
43
+ when /^target set ([^\s]+)( (\d+) (\d+))?$/
44
+ @targets[$1] = $2 ? [$3.to_i, $4.to_i] : @launcher.position
45
+ return [:target_set, @targets[$1]].flatten
46
+ when /^target ((get)|(del)) ([^\s]+)$/
47
+ if @targets.has_key?($+)
48
+ if $1 == "del"
49
+ @targets.delete($+)
50
+ return [:target_del]
51
+ else
52
+ return [:target_get, @targets[$+]].flatten
53
+ end
54
+ else
55
+ return [:notarget]
56
+ end
57
+ when /^((up)|(down)|(left)|(right)) (\d+)$/
58
+ @launcher.send($1, $+.to_i)
59
+ return [:move]
60
+ else
61
+ return [:badcommand]
62
+ end
63
+ else
64
+ return [:unauthorized]
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,26 @@
1
+ module HWPing
2
+ class HWPing
3
+
4
+ attr_reader :bot
5
+
6
+ def initialize(config = {})
7
+ @config = Config.new(config)
8
+ @launcher = Launcher.connect()
9
+ @handler = Handler.new(@launcher, @config)
10
+ @bot = Bot.new(@handler, @config)
11
+ end
12
+
13
+ def start
14
+ @bot.start
15
+ end
16
+
17
+ def stop
18
+ @bot.quit
19
+ end
20
+
21
+ # Return the configuration hash for an export
22
+ def config
23
+ @config.to_hash
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,136 @@
1
+ # Inspired by https://github.com/robhurring/thunder/blob/master/lib/launcher.rb
2
+ require 'libusb'
3
+
4
+ module HWPing
5
+ class Launcher
6
+
7
+ DeviceNotFoundError = Class.new(IOError)
8
+
9
+ DEVICE = {
10
+ :vendor_id => 0x2123,
11
+ :product_id => 0x1010
12
+ }
13
+
14
+ COMMANDS = {
15
+ :down => 0x01,
16
+ :up => 0x02,
17
+ :left => 0x04,
18
+ :right => 0x08,
19
+ :fire => 0x10,
20
+ :stop => 0x20,
21
+ :on => 0x01,
22
+ :off => 0x00
23
+ }
24
+
25
+ TARGETS = {
26
+ :launcher => 0x02,
27
+ :led => 0x03
28
+ }
29
+
30
+ REQUEST_TYPE = 0x21
31
+ REQUEST = 0x09
32
+
33
+ # Connect to the device
34
+ def self.connect
35
+ usb = LIBUSB::Context.new
36
+ launcher = usb.devices(
37
+ :idVendor => DEVICE[:vendor_id],
38
+ :idProduct => DEVICE[:product_id]
39
+ ).first
40
+
41
+ raise DeviceNotFoundError, 'Launcher was not found.' if launcher.nil?
42
+ new(launcher)
43
+ end
44
+
45
+ def initialize(device)
46
+ @device = device
47
+ @handle = @device.open
48
+ @handle.detach_kernel_driver(0) if @handle.kernel_driver_active?(0)
49
+ @x = 0
50
+ @y = 0
51
+ end
52
+
53
+ # Point at the given location and fire a rocket
54
+ def point_and_fire(arr)
55
+ led(:on)
56
+ reset
57
+ right arr[0]
58
+ up arr[1]
59
+ fire
60
+ led(:off)
61
+ end
62
+
63
+ # Get the relative position
64
+ def position
65
+ [@x, @y]
66
+ end
67
+
68
+ # Switch the LED on/off
69
+ def led(status)
70
+ send! :led, status
71
+ end
72
+
73
+ # Fire a rocket and wait for the device to reload
74
+ def fire
75
+ send! :launcher, :fire
76
+ Kernel.sleep 4.5
77
+ end
78
+
79
+ # Resets the launcher into the default position
80
+ def reset
81
+ down(1000)
82
+ left(6000) # should be enough
83
+ @x = 0
84
+ @y = 0
85
+ end
86
+
87
+ # Positioning functions
88
+ [:up, :down, :left, :right].each do |direction|
89
+ define_method direction do |duration|
90
+ move direction, duration
91
+ end
92
+ end
93
+
94
+ # Not really the best motor control
95
+ def move(direction, duration)
96
+ send! :launcher, direction
97
+ Kernel.sleep duration.to_f / 1000
98
+ send! :launcher, :stop
99
+ update_pos direction, duration
100
+ end
101
+
102
+ private
103
+ # Send data through USB
104
+ def send!(target, command)
105
+ payload = build_payload(target, COMMANDS[command.to_sym])
106
+
107
+ @handle.control_transfer(
108
+ bmRequestType: REQUEST_TYPE,
109
+ bRequest: REQUEST,
110
+ wValue: 0,
111
+ wIndex: 0,
112
+ dataOut: payload,
113
+ timeout: 0
114
+ )
115
+ end
116
+
117
+ def build_payload(target, command)
118
+ [TARGETS[target], command, 0, 0, 0, 0, 0, 0].pack('CCCCCCCC')
119
+ end
120
+
121
+ # Update inner position variables
122
+ def update_pos(direction, value)
123
+ value = value.to_i
124
+ case direction
125
+ when :up
126
+ @y = [1000, @y + value].min
127
+ when :down
128
+ @y = [0, @y - value].max
129
+ when :right
130
+ @x = [6000, @x + value].min
131
+ when :left
132
+ @x = [0, @x - value].max
133
+ end
134
+ end
135
+ end
136
+ end
data/lib/hwping.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'hwping/constants'
2
+ require 'hwping/config'
3
+ require 'hwping/launcher'
4
+ require 'hwping/handler'
5
+ require 'hwping/bot'
6
+ require 'hwping/hwping'
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hwping
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dávid Halász
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: libusb
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.5.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.5.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: cinch
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.2.4
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.2.4
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 10.4.2
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 10.4.2
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ description: IRC bot for HW pinging with the Dream Cheeky Thunder missile launcher
70
+ email: skateman@skateman.eu
71
+ executables:
72
+ - hwping
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - lib/hwping/handler.rb
77
+ - lib/hwping/launcher.rb
78
+ - lib/hwping/hwping.rb
79
+ - lib/hwping/bot.rb
80
+ - lib/hwping/config.rb
81
+ - lib/hwping/constants.rb
82
+ - lib/hwping.rb
83
+ - bin/hwping
84
+ homepage: http://github.com/skateman/hwping
85
+ licenses:
86
+ - GPL-2
87
+ metadata: {}
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 2.0.0
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 2.0.14
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: Hardware Pinger
108
+ test_files: []