onkyo_eiscp_ruby 0.0.3 → 2.1.2
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 +5 -5
- data/README.md +182 -32
- data/VERSION +1 -1
- data/bin/mock_receiver.rb +25 -0
- data/bin/onkyo.rb +85 -25
- data/bin/{onkyo-server.rb → onkyo_server.rb} +2 -1
- data/eiscp-commands.yaml +3911 -3900
- data/lib/eiscp.rb +8 -5
- data/lib/eiscp/dictionary.rb +54 -0
- data/lib/eiscp/dictionary/dictionary_generators.rb +63 -0
- data/lib/eiscp/dictionary/dictionary_helpers.rb +121 -0
- data/lib/eiscp/message.rb +98 -74
- data/lib/eiscp/parser.rb +24 -0
- data/lib/eiscp/parser/dynamic_value_parser.rb +9 -0
- data/lib/eiscp/parser/eiscp_parser.rb +37 -0
- data/lib/eiscp/parser/human_readable_parser.rb +29 -0
- data/lib/eiscp/parser/iscp_parser.rb +28 -0
- data/lib/eiscp/receiver.rb +158 -135
- data/lib/eiscp/receiver/command_methods.rb +28 -0
- data/lib/eiscp/receiver/discovery.rb +49 -0
- data/onkyo_eiscp_ruby.gemspec +15 -13
- data/test/tc_dictionary.rb +45 -0
- data/test/tc_message.rb +11 -12
- data/test/tc_parser.rb +34 -0
- data/test/tc_receiver.rb +4 -3
- metadata +23 -12
- data/lib/eiscp/command.rb +0 -99
- data/lib/eiscp/mock_receiver.rb +0 -22
- data/test/tc_command.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8e9c2fd0e9e79716c2b0a084a6dd7859597732f86fb71c1f4bcd4462c8e9297b
|
4
|
+
data.tar.gz: df71853616b26d2f62f6490b99f263d2a5bb2590c4de4bc7b1930fab14604ea5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5377a5163b1219647c708b0d125b1359108d3ebbd91bd4f2c8916a002aa4b83363d2531e0340deddc77a2251e2701cd26cb4fe9ab3b4a4c551a496ed2c20d6b0
|
7
|
+
data.tar.gz: fabc67566fb94c98b743c1db76173f86e3de03333ccad16dda9e5dbeb09747a2bad4ec62867593de404633065819644f0574e22c2c492e209d6f0bf17a609482
|
data/README.md
CHANGED
@@ -1,21 +1,42 @@
|
|
1
1
|
onkyo_eiscp_ruby
|
2
2
|
================
|
3
3
|
[](http://badge.fury.io/rb/onkyo_eiscp_ruby)
|
4
|
+
[](http://badge.fury.io/gh/mikerodrigues%2Fonkyo_eiscp_ruby)
|
4
5
|
|
5
|
-
A Ruby implementation of eISCP for controlling Onkyo receivers
|
6
|
+
*A Ruby implementation of eISCP for controlling Onkyo receivers.*
|
7
|
+
|
8
|
+
**This code is not really still under development and using it might still make you sick.**
|
9
|
+
|
10
|
+
**The python version linked below sees much more activity.**
|
11
|
+
|
12
|
+
Automatically discover receivers in the broadcast domain
|
13
|
+
|
14
|
+
Send commands to receivers and parse returned messages
|
15
|
+
|
16
|
+
Open a TCP socket to receive solicited and non-solicited status updates.
|
6
17
|
|
7
|
-
**This code is still under heavy development and using it might make you sick.**
|
8
|
-
Create ISCP messages and eISCP packets
|
9
|
-
Automatically discover receiver's in the broadcast domain
|
10
|
-
Send/Recieve eISCP messages
|
11
|
-
Open a TCP socket to send commands and receive solicited and non-solicited status updates.
|
12
18
|
Mock reciever (currently only responds to discovery)
|
13
19
|
|
20
|
+
Human-readable commands
|
21
|
+
|
14
22
|
**Inspired by https://github.com/miracle2k/onkyo-eiscp
|
15
23
|
|
16
24
|
**Protocol information from http://michael.elsdoerfer.name/onkyo/ISCP-V1.21_2011.xls
|
17
25
|
|
26
|
+
What's missing?
|
27
|
+
---------------
|
28
|
+
* Command validation
|
29
|
+
|
30
|
+
* Parsing of all human readable commands (run the tests to see some commands that aren't parsable in human readable form yet.
|
18
31
|
|
32
|
+
* Reasonable variants for human-readable commands (ex. `main-volume` or`volume
|
33
|
+
` as opposed to `master-volume`)
|
34
|
+
|
35
|
+
* Model compatability checking
|
36
|
+
|
37
|
+
* Logging
|
38
|
+
|
39
|
+
* Exhaustive testing and documentation
|
19
40
|
|
20
41
|
Using the Library
|
21
42
|
-----------------
|
@@ -23,53 +44,182 @@ Using the Library
|
|
23
44
|
|
24
45
|
require 'eiscp'
|
25
46
|
|
26
|
-
*
|
27
|
-
|
47
|
+
* You might want to `include EISCP` if you know you won't pollute your namespace
|
48
|
+
with Constants under `EISCP` (`Dictionary`, `Message`, `Parser`, `Receiver`,
|
49
|
+
`VERSION`)
|
50
|
+
|
51
|
+
* You can do most everything through the `Receiver` and `Message` objects. If you
|
52
|
+
want to accept user input you will probably want to use the Parser module. Be
|
53
|
+
sure to check out the RDocs or dig through the source code. I try to keep it
|
54
|
+
well commented/documented, and there's more functionality to the library than
|
55
|
+
is shown here:
|
56
|
+
|
57
|
+
* The `Message` object is pretty self explanatory. `Message.new` is mostly used
|
58
|
+
internally, but you're better off using `Parser.parse` to create them. You
|
59
|
+
probably will want to interact with `Message` objects to get information:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
msg = EISCP::Message.new(command: 'PWR', value: '01')
|
63
|
+
msg.zone => 'main'
|
64
|
+
msg.command => "PWR"
|
65
|
+
msg.value => "01"
|
66
|
+
msg.command_name => "system-power"
|
67
|
+
msg.command_description => "System Power Command"
|
68
|
+
msg.value_name => "on"
|
69
|
+
msg.value_description => "sets System On"
|
70
|
+
```
|
71
|
+
|
72
|
+
* Discover local receivers (returns an `Array` of `Receiver` objects)
|
73
|
+
|
74
|
+
```ruby
|
28
75
|
EISCP::Receiver.discover
|
76
|
+
```
|
29
77
|
|
30
|
-
* Create Receiver object from first discovered
|
78
|
+
* Create `Receiver` object from first discovered Receiver on the LAN
|
31
79
|
|
32
|
-
|
80
|
+
```ruby
|
81
|
+
receiver = EISCP::Receiver.new
|
82
|
+
```
|
33
83
|
|
34
|
-
*
|
84
|
+
* Or create one manually by IP address or hostname
|
35
85
|
|
36
|
-
|
37
|
-
receiver.
|
86
|
+
```ruby
|
87
|
+
receiver = EISCP::Receiver.new('10.0.0.132')
|
88
|
+
```
|
38
89
|
|
39
|
-
*
|
90
|
+
* When you create a `Receiver` object with a callback block it will
|
91
|
+
connect and call your block on each message received.:
|
40
92
|
|
41
|
-
|
42
|
-
|
93
|
+
```ruby
|
94
|
+
receiver = EISCP::Receiver.new do |msg|
|
95
|
+
puts msg.command
|
96
|
+
puts msg.value
|
43
97
|
end
|
98
|
+
```
|
44
99
|
|
45
|
-
*
|
100
|
+
* Receivers created without a block will not connect automatically. You can use
|
101
|
+
the `connect` method to create a socket and connect to the receiver.
|
46
102
|
|
47
|
-
|
48
|
-
|
103
|
+
```ruby
|
104
|
+
receiver.connect
|
105
|
+
```
|
49
106
|
|
50
|
-
*
|
51
|
-
|
52
|
-
|
53
|
-
iscp_message = EISCP::Message.parse "PWR01"
|
54
|
-
iscp_message = EISCP::Message.parse "PWR 01"
|
55
|
-
iscp_message = EISCP::Message.parse "!1PWR01"
|
56
|
-
iscp_message = EISCP::Message.parse "!1PWR 01"
|
107
|
+
* You can also set or change the callback block later. This will kill the
|
108
|
+
existing callback thread, recreate the socket if necessary and start
|
109
|
+
a new callback thread using the provided block:
|
57
110
|
|
58
|
-
|
111
|
+
```ruby
|
112
|
+
receiver.connect do |msg|
|
113
|
+
puts "Received: #{msg.command_name}:#{msg.value_name}"
|
114
|
+
end
|
115
|
+
```
|
116
|
+
|
117
|
+
* You can also disconnect, which will close the socket and kill the connection
|
118
|
+
thread:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
receiver.disconnect
|
122
|
+
```
|
123
|
+
|
124
|
+
* Get information about the Receiver:
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
receiver.model => "TX-NR609"
|
128
|
+
receiver.host => "10.0.0.111"
|
129
|
+
receiver.port => 60128
|
130
|
+
receiver.mac_address => "001122334455"
|
131
|
+
receiver.area => "DX"
|
132
|
+
```
|
133
|
+
|
134
|
+
* Receivers now have a `@state` hash that contains a mapping of commands and
|
135
|
+
values received. You can use this see the Receiver's last known state without
|
136
|
+
querying. Use the `#update_state` method to run every 'QSTN' command in the
|
137
|
+
Dictionary and update the state hash, but do note that it will take a few
|
138
|
+
seconds to finish:
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
receiver.update_state
|
142
|
+
receiver.state["MVL"] => "22"
|
143
|
+
receiver.human_readable_state["master-volume"] => 34
|
144
|
+
```
|
145
|
+
|
146
|
+
|
147
|
+
* You can use `CommandMethods` to easily send a message and return the reply as
|
148
|
+
a Message object. Once `Receiver#connect`is called, a method is defined for each command listed in the
|
149
|
+
`Dictionary` using the `@command_name` attribute which is 'human readable'.
|
150
|
+
You can check the included yaml file or look at the output of
|
151
|
+
`EISCP::Dictionary.commands`. Here a few examples:
|
152
|
+
|
153
|
+
```ruby
|
154
|
+
# Turn on receiver
|
155
|
+
receiver.system_power "on"
|
156
|
+
|
157
|
+
# Query current input source
|
158
|
+
receiver.input_selector "query"
|
159
|
+
|
160
|
+
# Turn the master volume up one level
|
161
|
+
receiver.master_volume "level-up"
|
162
|
+
|
163
|
+
# Set the master volume to 45
|
164
|
+
receiver.master_volume "45"
|
165
|
+
```
|
166
|
+
|
167
|
+
* Parse ISCP and human readable strings:
|
168
|
+
|
169
|
+
```ruby
|
170
|
+
# Parse various ISCP strings
|
171
|
+
iscp_message = EISCP::Parser.parse "PWR01"
|
172
|
+
iscp_message = EISCP::Parser.parse "PWR 01"
|
173
|
+
iscp_message = EISCP::Parser.parse "!1PWR01"
|
174
|
+
iscp_message = EISCP::Parser.parse "!1PWR 01"
|
175
|
+
|
176
|
+
# Parse human readable,
|
177
|
+
EISCP::Parser.parse("main-volume 34")
|
178
|
+
```
|
179
|
+
|
180
|
+
* `Parser.parse` is also used internally by `Receiver` to parse raw eISCP socket
|
181
|
+
data.
|
59
182
|
|
60
|
-
iscp_message_from_raw_eiscp = EISCP::Message.parse iscp_message.to_eiscp
|
61
183
|
|
62
184
|
Using the Binaries
|
63
185
|
------------------
|
64
186
|
|
65
187
|
* Discover local receivers
|
66
188
|
|
67
|
-
|
189
|
+
`$ onkyo.rb -d`
|
190
|
+
|
191
|
+
* Send a human-readable command
|
192
|
+
|
193
|
+
`$ onkyo.rb system-power on # uses Parser.parse`
|
194
|
+
|
195
|
+
* Or send a raw command
|
68
196
|
|
69
|
-
|
197
|
+
`$ onkyo.rb PWRQSTN # Also tries to use Parser.parse`
|
70
198
|
|
71
|
-
|
199
|
+
* Monitor the first discovered receiver to see status updates
|
200
|
+
|
201
|
+
`$ onkyo.rb -m`
|
72
202
|
|
73
203
|
* Start the mock server (only responds to 'ECNQSTN')
|
74
204
|
|
75
|
-
|
205
|
+
`$ onkyo-server.rb`
|
206
|
+
|
207
|
+
* Turn off the first receiver discovered:
|
208
|
+
|
209
|
+
`$ onkyo.rb system-power off`
|
210
|
+
|
211
|
+
* List all known commands and values:
|
212
|
+
|
213
|
+
`$ onkyo.rb -L`
|
214
|
+
|
215
|
+
* List all known commands known to work with discovered models:
|
216
|
+
|
217
|
+
`$ onkyo.rb -l`
|
218
|
+
|
219
|
+
Contributing
|
220
|
+
------------
|
221
|
+
|
222
|
+
* Open an issue describing bug or feature
|
223
|
+
* Fork repo
|
224
|
+
* Create a branch
|
225
|
+
* Send pull request
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.1.2
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'socket'
|
4
|
+
require_relative './receiver'
|
5
|
+
require_relative './message'
|
6
|
+
|
7
|
+
# Mock server that only responds to ECNQSTN.
|
8
|
+
|
9
|
+
module EISCP
|
10
|
+
# This class acts as an Onkyo Stereo. It can be used for testing
|
11
|
+
#
|
12
|
+
class MockReceiver
|
13
|
+
DISCOVERY_IP = '255.255.255.255'
|
14
|
+
ONKYO_DISCOVERY_RESPONSE = Message.new('ECN', "TX-NR609/60128/DX/14DAE9E967C8\x19\r\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
|
15
|
+
|
16
|
+
# Create/start the server object.
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
Socket.udp_server_loop(DISCOVERY_IP, Receiver::ONKYO_PORT) do |msg, src|
|
20
|
+
src.reply "ISCP\x00\x00\x00\x10\x00\x00\x00&\x01\x00\x00\x00!1ECNTX-NR609/60128/DX/14DAE9E967C8\x19\r\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
21
|
+
puts msg
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/bin/onkyo.rb
CHANGED
@@ -1,17 +1,20 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'eiscp'
|
4
5
|
require 'optparse'
|
5
6
|
require 'ostruct'
|
7
|
+
|
8
|
+
# This object parses ARGV and returns an @option hash
|
9
|
+
#
|
6
10
|
class Options
|
7
|
-
DEFAULT_OPTIONS = { verbose: true, all: false }
|
11
|
+
DEFAULT_OPTIONS = { verbose: true, all: false }.freeze
|
8
12
|
USAGE = ' Usage: onkyo_rb [options]'
|
9
13
|
|
10
14
|
def self.parse(args)
|
11
15
|
@options = OpenStruct.new
|
12
16
|
|
13
17
|
options = OptionParser.new do |opts|
|
14
|
-
|
15
18
|
opts.banner = USAGE
|
16
19
|
|
17
20
|
opts.on '-d', '--discover', 'Find Onkyo Receivers on the local broadcast domain' do |d|
|
@@ -34,53 +37,110 @@ class Options
|
|
34
37
|
@options.list_all = l
|
35
38
|
end
|
36
39
|
|
37
|
-
opts.on '-
|
38
|
-
@options.
|
40
|
+
opts.on '-m', '--monitor', 'Connect to the first discovered reciever and monitor updates' do |m|
|
41
|
+
@options.monitor = m
|
39
42
|
end
|
40
|
-
|
41
43
|
end
|
42
44
|
|
43
45
|
options.parse!(args)
|
44
46
|
|
45
|
-
if @options
|
46
|
-
puts options
|
47
|
-
end
|
47
|
+
puts options if @options.nil? && ARGV == []
|
48
48
|
|
49
49
|
if @options.discover
|
50
|
-
EISCP::Receiver.discover.each
|
51
|
-
puts EISCP::Message.parse(receiver[0]).to_iscp
|
52
|
-
end
|
50
|
+
EISCP::Receiver.discover.each { |rec| puts "#{rec.host}:#{rec.port} - #{rec.model} - #{rec.mac_address}" }
|
53
51
|
exit 0
|
54
52
|
end
|
55
53
|
|
56
54
|
if @options.help
|
57
55
|
puts options
|
58
|
-
exit 0
|
56
|
+
exit 0
|
57
|
+
end
|
58
|
+
|
59
|
+
if @options.monitor
|
60
|
+
begin
|
61
|
+
rec = EISCP::Receiver.new do |reply|
|
62
|
+
puts "#{Time.now} #{rec.host} "\
|
63
|
+
"#{reply.zone}: "\
|
64
|
+
"#{reply.command_description || reply.command} "\
|
65
|
+
"-> #{reply.value_description || reply.value}"
|
66
|
+
end
|
67
|
+
rec.thread.join
|
68
|
+
rescue Interrupt
|
69
|
+
raise 'Exiting...'
|
70
|
+
rescue Exception => e
|
71
|
+
puts 'bummer...'
|
72
|
+
puts e
|
73
|
+
end
|
59
74
|
end
|
60
75
|
|
61
|
-
if @options.
|
62
|
-
|
63
|
-
|
64
|
-
|
76
|
+
if @options.list
|
77
|
+
models = []
|
78
|
+
modelsets = []
|
79
|
+
EISCP::Receiver.discover.each do |rec|
|
80
|
+
models << rec.model
|
81
|
+
end
|
82
|
+
models.each do |model|
|
83
|
+
EISCP::Dictionary.modelsets.each do |modelset, list|
|
84
|
+
modelsets << modelset unless list.select { |x| x.match model }.empty?
|
85
|
+
end
|
86
|
+
end
|
87
|
+
EISCP::Dictionary.zones.each do |zone|
|
88
|
+
EISCP::Dictionary.commands[zone].each do |command, command_hash|
|
89
|
+
puts 'Command - Description'
|
90
|
+
puts "\n"
|
91
|
+
puts " '#{Dictionary.command_to_name(command)}' - "\
|
92
|
+
"#{Dictionary.description_from_command(command)}"
|
93
|
+
puts "\n"
|
94
|
+
puts ' Value - Description>'
|
95
|
+
puts "\n"
|
96
|
+
command_hash[:values].each do |_value, attr_hash|
|
97
|
+
if modelsets.include? attr_hash[:models]
|
98
|
+
puts " '#{EISCP::Dictionary.command_value_to_value_name(command, _value)}' - "\
|
99
|
+
" #{attr_hash[:description]}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
puts "\n"
|
103
|
+
end
|
65
104
|
end
|
66
105
|
end
|
67
106
|
|
107
|
+
if @options.list_all
|
108
|
+
EISCP::Dictionary.zones.each do |zone|
|
109
|
+
EISCP::Dictionary.commands[zone].each do |command, command_hash|
|
110
|
+
puts 'Command - Description'
|
111
|
+
puts "\n"
|
112
|
+
puts " '#{Dictionary.command_to_name(command)}' - "\
|
113
|
+
"#{Dictionary.description_from_command(command)}"
|
114
|
+
puts "\n"
|
115
|
+
puts ' Value - Description>'
|
116
|
+
puts "\n"
|
117
|
+
command_hash[:values].each do |_value, attr_hash|
|
118
|
+
puts " '#{EISCP::Dictionary.command_value_to_value_name(command, _value)}' - "\
|
119
|
+
" #{attr_hash[:description]}"
|
120
|
+
end
|
121
|
+
puts "\n"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
exit 0
|
125
|
+
end
|
126
|
+
|
68
127
|
if ARGV == []
|
69
128
|
puts options
|
70
129
|
exit 0
|
71
130
|
end
|
72
131
|
end
|
73
|
-
|
74
132
|
end
|
75
133
|
|
134
|
+
include EISCP
|
76
135
|
|
77
136
|
@options = Options.parse(ARGV)
|
78
137
|
|
79
|
-
|
80
|
-
receiver
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
138
|
+
receiver = EISCP::Receiver.discover[0]
|
139
|
+
receiver.connect
|
140
|
+
begin
|
141
|
+
command = EISCP::Parser.parse(ARGV.join(' '))
|
142
|
+
rescue StandardError
|
143
|
+
raise "Couldn't parse command"
|
144
|
+
end
|
145
|
+
reply = receiver.send_recv(command)
|
146
|
+
puts "#{Time.now}: Response from #{receiver.host}: #{reply.zone.capitalize} #{reply.command_description || reply.command} -> #{reply.value_description || reply.value}"
|