onkyo_eiscp_ruby 0.0.2 → 2.1.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.
data/test/tc_parser.rb ADDED
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/eiscp/parser'
4
+ require_relative '../lib/eiscp/message'
5
+ require 'minitest/autorun'
6
+
7
+ class TestParser < MiniTest::Test
8
+ DISCOVERY_PACKET = EISCP::Message.new(command: 'ECN', value: 'QSTN', terminator: "\r\n", unit_type: 'x', start: '!')
9
+ DISCOVERY_STRING = DISCOVERY_PACKET.to_eiscp
10
+
11
+ def test_parse_discovery_iscp_message
12
+ assert_equal(EISCP::Parser.parse('!xECNQSTN').to_iscp, '!xECNQSTN')
13
+ end
14
+
15
+ def test_parse_iscp_messages
16
+ assert_equal(EISCP::Parser.parse('PWR 01').to_iscp, '!1PWR01')
17
+ assert_equal(EISCP::Parser.parse('PWR01').to_iscp, '!1PWR01')
18
+ assert_equal(EISCP::Parser.parse('!1PWR01').to_iscp, '!1PWR01')
19
+ assert_equal(EISCP::Parser.parse('!1PWR 01').to_iscp, '!1PWR01')
20
+ end
21
+
22
+ def test_parse_discovery_packet_string
23
+ assert_equal(EISCP::Parser.parse(DISCOVERY_STRING).to_eiscp, DISCOVERY_PACKET.to_eiscp)
24
+ end
25
+
26
+ def test_parse_human_readable
27
+ assert_equal(EISCP::Parser.parse('system-power on'), EISCP::Message.new(command: 'PWR', value: '01'))
28
+ assert_equal(EISCP::Parser.parse('main system-power on'), EISCP::Message.new(command: 'PWR', value: '01'))
29
+ end
30
+
31
+ def test_return_nil_for_fake_human_readable
32
+ assert_equal(EISCP::Parser.parse('fake-command value'), nil)
33
+ end
34
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/eiscp/receiver'
4
+ require 'minitest/autorun'
5
+
6
+ class TestEISCP
7
+ end
metadata CHANGED
@@ -1,69 +1,74 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: onkyo_eiscp_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
5
- prerelease:
4
+ version: 2.1.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Michael Rodrigues
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2014-01-02 00:00:00.000000000 Z
11
+ date: 2021-03-21 00:00:00.000000000 Z
13
12
  dependencies: []
14
- description: ! "\n Use the provided binary script or require the library for use
15
- in your scripts.\n "
13
+ description: "\n Control Onkyo receivers over the network.Use the provided binary
14
+ or\n require the library for use in your scripts.\n "
16
15
  email: mikebrodrigues@gmail.com
17
16
  executables:
18
17
  - onkyo.rb
19
- - onkyo-server.rb
18
+ - onkyo_server.rb
20
19
  extensions: []
21
20
  extra_rdoc_files:
22
21
  - README.md
23
22
  files:
24
- - bin/onkyo-server.rb
23
+ - README.md
24
+ - VERSION
25
+ - bin/mock_receiver.rb
25
26
  - bin/onkyo.rb
26
- - lib/eiscp/eiscp_server.rb
27
- - lib/eiscp/eiscp.rb
28
- - lib/eiscp/eiscp_packet.rb
29
- - lib/eiscp/command.rb
30
- - lib/eiscp/iscp_message.rb
27
+ - bin/onkyo_server.rb
28
+ - eiscp-commands.yaml
31
29
  - lib/eiscp.rb
32
- - test/tc_command.rb
33
- - test/tc_iscp_message.rb
34
- - test/tc_eiscp.rb
35
- - test/tc_eiscp_packet.rb
36
- - VERSION
30
+ - lib/eiscp/dictionary.rb
31
+ - lib/eiscp/dictionary/dictionary_generators.rb
32
+ - lib/eiscp/dictionary/dictionary_helpers.rb
33
+ - lib/eiscp/message.rb
34
+ - lib/eiscp/parser.rb
35
+ - lib/eiscp/parser/dynamic_value_parser.rb
36
+ - lib/eiscp/parser/eiscp_parser.rb
37
+ - lib/eiscp/parser/human_readable_parser.rb
38
+ - lib/eiscp/parser/iscp_parser.rb
39
+ - lib/eiscp/receiver.rb
40
+ - lib/eiscp/receiver/command_methods.rb
41
+ - lib/eiscp/receiver/discovery.rb
37
42
  - onkyo_eiscp_ruby.gemspec
38
- - eiscp-commands.yaml
39
- - README.md
43
+ - test/tc_dictionary.rb
44
+ - test/tc_message.rb
45
+ - test/tc_parser.rb
46
+ - test/tc_receiver.rb
40
47
  homepage: https://github.com/mikerodrigues/onkyo_eiscp_ruby
41
- licenses: []
48
+ licenses:
49
+ - MIT
50
+ metadata: {}
42
51
  post_install_message:
43
52
  rdoc_options: []
44
53
  require_paths:
45
54
  - lib
46
55
  required_ruby_version: !ruby/object:Gem::Requirement
47
- none: false
48
56
  requirements:
49
- - - ! '>='
57
+ - - ">="
50
58
  - !ruby/object:Gem::Version
51
59
  version: '0'
52
60
  required_rubygems_version: !ruby/object:Gem::Requirement
53
- none: false
54
61
  requirements:
55
- - - ! '>='
62
+ - - ">="
56
63
  - !ruby/object:Gem::Version
57
64
  version: '0'
58
65
  requirements: []
59
- rubyforge_project:
60
- rubygems_version: 1.8.25
66
+ rubygems_version: 3.2.3
61
67
  signing_key:
62
- specification_version: 3
68
+ specification_version: 4
63
69
  summary: Manipulate Onkyo stereos with the eISCP protocol
64
70
  test_files:
65
- - test/tc_command.rb
66
- - test/tc_iscp_message.rb
67
- - test/tc_eiscp.rb
68
- - test/tc_eiscp_packet.rb
69
- has_rdoc:
71
+ - test/tc_dictionary.rb
72
+ - test/tc_message.rb
73
+ - test/tc_parser.rb
74
+ - test/tc_receiver.rb
data/bin/onkyo-server.rb DELETED
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'eiscp/eiscp_server'
4
-
5
- puts "Starting server on 60128..."
6
-
7
- EISCPServer.new
data/lib/eiscp/command.rb DELETED
@@ -1,80 +0,0 @@
1
- require 'yaml'
2
- require 'eiscp/eiscp'
3
- require 'ostruct'
4
-
5
- module Command
6
-
7
- @@yaml_file_path = File.join(File.expand_path(File.dirname(__FILE__)), '../../eiscp-commands.yaml')
8
- @@yaml_object = YAML.load(File.read(@@yaml_file_path))
9
- @@modelsets = @@yaml_object["modelsets"]
10
- @@yaml_object.delete("modelsets")
11
- @@zones = @@yaml_object.map{|k, v| k}
12
- @@zones.each {|zone| class_variable_set("@@#{zone}", nil) }
13
- @@main = @@yaml_object['main']
14
-
15
-
16
- @@zones.each do |zone|
17
- Command.class_variable_set("@@#{zone}", "[]")
18
- end
19
-
20
-
21
-
22
- def self.command_to_name(command)
23
- return @@main[command]['name']
24
- end
25
-
26
- def self.name_to_command(name)
27
- @@main.each_pair do |command, attrs|
28
- if attrs['name'] == name
29
- return command
30
- end
31
- end
32
- end
33
-
34
- def self.command_value_to_value_name(command, value)
35
- return @@main[command]['values'][value]['name']
36
- end
37
-
38
- def self.command_value_name_to_value(command, name)
39
- @@main[command]['values'].each do |k, v|
40
- if v['name'] == name.to_s
41
- return k
42
- end
43
- end
44
- end
45
-
46
-
47
- def self.description_from_name(name)
48
- @@main.each_pair do |command, attrs|
49
- if attrs['name'] == name
50
- return command['description']
51
- end
52
- end
53
- end
54
-
55
- def self.description_from_command(command)
56
- return @@main[command]['description']
57
- end
58
-
59
- def self.description_from_command_value(command, value)
60
- return @@main[command]['values'].select do |k, v|
61
- if k == value
62
- return v['description']
63
- end
64
- end
65
- end
66
-
67
- def self.list_all_commands
68
- @@main.each_pair do |command, attrs|
69
- puts "#{command} - #{attrs['name']}: #{attrs['description']}"
70
- attrs['values'].each_pair do |k, v|
71
- puts "--#{k}:#{v}"
72
- end
73
- end
74
- end
75
-
76
- def self.list_compatible_commands
77
-
78
- end
79
- end
80
-
data/lib/eiscp/eiscp.rb DELETED
@@ -1,125 +0,0 @@
1
- require 'socket'
2
- require 'eiscp/eiscp_packet.rb'
3
- require 'eiscp/iscp_message.rb'
4
-
5
- class EISCP
6
- ONKYO_PORT = 60128
7
- ONKYO_MAGIC = EISCPPacket.new("ECN", "QSTN", "x").to_s
8
-
9
- # Create a new EISCP object to communicate with a receiver.
10
-
11
- def initialize(host)
12
- @host = host
13
- end
14
-
15
- # Internal method for receiving data with a timeout
16
-
17
- def self.recv(sock, timeout = 0.5)
18
- data = []
19
- while true
20
- ready = IO.select([sock], nil, nil, timeout)
21
- if ready != nil
22
- then readable = ready[0]
23
- else
24
- return data
25
- end
26
-
27
-
28
- readable.each do |socket|
29
- begin
30
- if socket == sock
31
- data << sock.recv_nonblock(1024).chomp
32
- end
33
- rescue IO::WaitReadable
34
- retry
35
- end
36
- end
37
-
38
- end
39
- end
40
-
41
- # Returns an array of arrays consisting of a discovery response packet string
42
- # and the source ip address of the reciever.
43
-
44
- def self.discover
45
- sock = UDPSocket.new
46
- sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
47
- sock.send(ONKYO_MAGIC, 0, '<broadcast>', ONKYO_PORT)
48
- data = []
49
- while true
50
- ready = IO.select([sock], nil, nil, 0.5)
51
- if ready != nil
52
- then readable = ready[0]
53
- else
54
- return data
55
- end
56
-
57
-
58
- readable.each do |socket|
59
- begin
60
- if socket == sock
61
- msg, addr = sock.recvfrom_nonblock(1024)
62
- data << [msg, addr[2]]
63
- end
64
- rescue IO::WaitReadable
65
- retry
66
- end
67
- end
68
-
69
- end
70
- end
71
-
72
- # Sends a packet string on the network
73
-
74
- def send(eiscp_packet)
75
- sock = TCPSocket.new @host, ONKYO_PORT
76
- sock.puts eiscp_packet
77
- sock.close
78
- end
79
-
80
- # Send a packet string and return recieved data string.
81
-
82
- def send_recv(eiscp_packet)
83
- sock = TCPSocket.new @host, ONKYO_PORT
84
- sock.puts eiscp_packet
85
- puts EISCP.recv(sock, 0.5)
86
- end
87
-
88
- # Open a TCP connection to the host and print all received messages until
89
- # killed.
90
-
91
- def connect(&block)
92
- sock = TCPSocket.new @host, ONKYO_PORT
93
- while true
94
- ready = IO.select([sock], nil, nil, nil)
95
- if ready != nil
96
- then readable = ready[0]
97
- else
98
- return
99
- end
100
-
101
- readable.each do |socket|
102
- begin
103
- if socket == sock
104
- data = sock.recv_nonblock(1024).chomp
105
- if block_given?
106
- yield data
107
- else
108
- puts data
109
- end
110
- end
111
- rescue IO::WaitReadable
112
- retry
113
- end
114
- end
115
-
116
- end
117
- end
118
-
119
- end
120
-
121
-
122
-
123
-
124
-
125
-
@@ -1,51 +0,0 @@
1
- require 'eiscp/iscp_message'
2
-
3
- # Public: Encapsulates ISCP Messages in eISCP packets to send on the network.
4
- # You can alsoe use the class method 'parse' to create objects from strings
5
- # captured from the network using the EISCP class.
6
-
7
- class EISCPPacket
8
-
9
- MAGIC = "ISCP"
10
- HEADER_SIZE = 16
11
- VERSION = "\x01"
12
- RESERVED = "\x00\x00\x00"
13
-
14
- attr_accessor :header
15
- attr_reader :iscp_message
16
-
17
- # Create a new EISCPPacket object with a given command and parameter
18
- # -+command+ - an ISCP command like "PWR" for "system-power"
19
- # -+parameter+ - an ISCP command parameter like "01" for "on" for
20
- # "system-power"
21
-
22
- def initialize(command, parameter, unit_type = "1", start = "!")
23
- @iscp_message = ISCPMessage.new(command, parameter, unit_type, start)
24
- @header = { :magic => MAGIC, :header_size => HEADER_SIZE, :data_size => @iscp_message.to_s.length, :version => VERSION, :reserved => RESERVED }
25
- end
26
-
27
- # Returns a raw packet string for sending on the network using EISCP object.
28
-
29
- def to_s
30
- return [ @header[:magic], @header[:header_size], @header[:data_size], @header[:version], @header[:reserved], @iscp_message.to_s ].pack("A4NNAa3A*")
31
- end
32
-
33
- # Returns an EISCPPacket from a raw packet string
34
-
35
- def self.parse(eiscp_message_string)
36
- array = eiscp_message_string.unpack("A4NNAa3A*")
37
- iscp_message = ISCPMessage.parse(array[5])
38
- packet = EISCPPacket.new(iscp_message.command, iscp_message.parameter, iscp_message.unit_type, iscp_message.start)
39
- packet.header = {
40
- :magic => array[0],
41
- :header_size => array[1],
42
- :data_size => array[2],
43
- :version => array[3],
44
- :reserved => array[4]
45
- }
46
- return packet
47
- end
48
-
49
- end
50
-
51
-
@@ -1,21 +0,0 @@
1
- require 'socket'
2
- require 'eiscp/eiscp_packet'
3
- require 'eiscp/eiscp'
4
-
5
- # Mock server that only responds to ECNQSTN.
6
-
7
- class EISCPServer
8
-
9
- ONKYO_DISCOVERY_RESPONSE = EISCPPacket.new("ECN", "TX-NR609/60128/DX/001122334455")
10
-
11
- # Create/start the server object.
12
-
13
- def initialize
14
- Socket.udp_server_loop("255.255.255.255", EISCP::ONKYO_PORT) do |msg, msg_src|
15
- msg_src.reply ONKYO_DISCOVERY_RESPONSE.to_s
16
- puts msg
17
- end
18
- end
19
-
20
- end
21
-
@@ -1,24 +0,0 @@
1
- class ISCPMessage
2
-
3
- attr_accessor :start
4
- attr_accessor :unit_type
5
- attr_accessor :command
6
- attr_accessor :parameter
7
-
8
- def initialize(command, parameter, unit_type = "1", start = "!")
9
- @unit_type = unit_type
10
- @start = start
11
- @command = command
12
- @parameter = parameter
13
- end
14
-
15
- def self.parse(msg_string)
16
- match = msg_string.match(/(?<start>!)(?<unit_type>\w)(?<command>[A-Z]{3})(?<parameter>\S+)/)
17
- ISCPMessage.new(match[:command], match[:parameter], match[:unit_type], match[:start])
18
- end
19
-
20
- def to_s
21
- return "#{@start + @unit_type + @command + @parameter}\r"
22
- end
23
-
24
- end