hwping 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bin/hwping +32 -0
- data/lib/hwping/bot.rb +67 -0
- data/lib/hwping/config.rb +24 -0
- data/lib/hwping/constants.rb +6 -0
- data/lib/hwping/handler.rb +68 -0
- data/lib/hwping/hwping.rb +26 -0
- data/lib/hwping/launcher.rb +136 -0
- data/lib/hwping.rb +6 -0
- metadata +108 -0
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,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
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: []
|