seriamp 0.1.2 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cd8d27d7818b801b6734b046fcc3682b1322bc03cfaa8d2472f4963d5974f7d5
4
- data.tar.gz: 917a111090ce967b0c28684f60fc0ccf8dca627c0c5d6ae1699b97746be69afc
3
+ metadata.gz: 630564090e5fbf436a4384d2aff86c3f51d8dcd60e69e82121730107dcb82deb
4
+ data.tar.gz: 4dfffa50df36bf315fb476d472d9de125e01c670c823e1c881b66189e5a5351b
5
5
  SHA512:
6
- metadata.gz: 166e4cc102b91987bcb244aee644b682757609ad19ea42eafb88216f09295b87344a7906d925ff0479fe58b4db477691404bcfb7211d9bab7b29d29fe41555f2
7
- data.tar.gz: 4e4aac13144356caeb92bf05da4e50181f1f83613e5ed1bb857fe91c1562d6d352b81c9e9eb051f6f8f50cc348f4bb61f0e8f04887880480dbc6e8c19be513de
6
+ metadata.gz: 2abd880200ab09af611fe31b31ca8299d189cf05f1448cc59773972f6c4e8929c120fdc533f2b7c246cde8a3621fbeeb6d562ef18f233b8b1ae63536708c2678
7
+ data.tar.gz: f110bb9840aac1b485c8e12f42b34cbb0d4a578d9f6e3852591480b59f450715d08da33b166e3eb4381152139aef3e0b8e09a9fd2a65be31a41183cfd7b4fa70
data/bin/sonamp-web CHANGED
@@ -25,7 +25,7 @@ logger = Logger.new(STDERR)
25
25
 
26
26
  #Sonamp::App.set :device, options[:device]
27
27
  #Sonamp::App.set :logger, logger
28
- Seriamp::Sonamp::App.set :client, Sonamp::Client.new(options[:device], logger: logger)
28
+ Seriamp::Sonamp::App.set :client, Seriamp::Sonamp::Client.new(device: options[:device], logger: logger)
29
29
 
30
30
  options = Rack::Server::Options.new.parse!(ARGV)
31
- Rack::Server.start(options.merge(app: Sonamp::App))
31
+ Rack::Server.start(options.merge(app: Seriamp::Sonamp::App))
data/bin/yamaha-web CHANGED
@@ -25,7 +25,7 @@ logger = Logger.new(STDERR)
25
25
 
26
26
  #Yamaha::App.set :device, options[:device]
27
27
  #Yamaha::App.set :logger, logger
28
- Seriamp::Yamaha::App.set :client, Yamaha::Client.new(options[:device], logger: logger)
28
+ Seriamp::Yamaha::App.set :client, Seriamp::Yamaha::Client.new(device: options[:device], logger: logger)
29
29
 
30
30
  options = Rack::Server::Options.new.parse!(ARGV)
31
- Rack::Server.start(options.merge(app: Yamaha::App))
31
+ Rack::Server.start(options.merge(app: Seriamp::Yamaha::App))
@@ -3,6 +3,7 @@
3
3
  require 'sinatra/base'
4
4
  require 'seriamp/utils'
5
5
  require 'seriamp/sonamp/client'
6
+ require 'seriamp/detect'
6
7
 
7
8
  module Seriamp
8
9
  module Sonamp
@@ -12,6 +13,10 @@ module Seriamp
12
13
  set :logger, nil
13
14
  set :client, nil
14
15
 
16
+ get '/' do
17
+ render_json(client.status)
18
+ end
19
+
15
20
  get '/power' do
16
21
  render_json(client.get_zone_power)
17
22
  end
@@ -55,6 +60,7 @@ module Seriamp
55
60
  end
56
61
 
57
62
  def render_json(data)
63
+ headers['content-type'] = 'application/json'
58
64
  data.to_json
59
65
  end
60
66
  end
@@ -69,11 +69,11 @@ module Seriamp
69
69
  client.set_zone_power(4, false)
70
70
  when 'power'
71
71
  zone = args.shift.to_i
72
- state = Utils.parse_on_off(ARGV.shift)
72
+ state = Utils.parse_on_off(args.shift)
73
73
  client.set_zone_power(zone, state)
74
74
  when 'zvol'
75
75
  zone = args.shift.to_i
76
- volume = ARGV.shift.to_i
76
+ volume = args.shift.to_i
77
77
  client.set_zone_volume(zone, volume)
78
78
  when 'cvol'
79
79
  channel = args.shift.to_i
@@ -81,7 +81,7 @@ module Seriamp
81
81
  client.set_channel_volume(channel, volume)
82
82
  when 'zmute'
83
83
  zone = args.shift.to_i
84
- mute = ARGV.shift.to_i
84
+ mute = args.shift.to_i
85
85
  client.set_zone_mute(zone, mute)
86
86
  when 'cmute'
87
87
  channel = args.shift.to_i
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Seriamp
4
- VERSION = '0.1.2'
4
+ VERSION = '0.1.4'
5
5
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'sinatra/base'
4
4
  require 'seriamp/utils'
5
+ require 'seriamp/detect'
5
6
  require 'seriamp/yamaha/client'
6
7
 
7
8
  module Seriamp
@@ -12,6 +13,10 @@ module Seriamp
12
13
  set :logger, nil
13
14
  set :client, nil
14
15
 
16
+ get '/' do
17
+ render_json(client.status)
18
+ end
19
+
15
20
  get '/power' do
16
21
  render_json(client.last_status.fetch(:power) > 0)
17
22
  end
@@ -27,15 +32,27 @@ module Seriamp
27
32
  empty_response
28
33
  end
29
34
 
30
- get '/#{zone}/volume' do
35
+ get "/#{zone}/volume" do
31
36
  render_json(client.public_send("get_#{zone}_volume"))
32
37
  end
33
38
 
34
- put '/#{zone}/volume' do
39
+ put "/#{zone}/volume" do
35
40
  value = Float(request.body.read)
36
41
  client.public_send("set_#{zone}_volume_db", value)
37
42
  empty_response
38
43
  end
44
+
45
+ put "/#{zone}/input" do
46
+ value = request.body.read
47
+ client.public_send("set_#{zone}_input", value)
48
+ empty_response
49
+ end
50
+ end
51
+
52
+ put "/pure-direct" do
53
+ state = Utils.parse_on_off(request.body.read)
54
+ client.public_send("set_pure_direct", state)
55
+ empty_response
39
56
  end
40
57
 
41
58
  private
@@ -47,6 +64,7 @@ module Seriamp
47
64
  end
48
65
 
49
66
  def render_json(data)
67
+ headers['content-type'] = 'application/json'
50
68
  data.to_json
51
69
  end
52
70
 
@@ -2,13 +2,13 @@
2
2
 
3
3
  require 'timeout'
4
4
  require 'seriamp/backend/serial_port'
5
- require 'seriamp/yamaha/protocol/constants'
6
5
  require 'seriamp/yamaha/protocol/methods'
7
6
 
8
7
  module Seriamp
9
8
  module Yamaha
10
9
 
11
- RS232_TIMEOUT = 3
10
+ # The manual says response should be received in 500 ms.
11
+ RS232_TIMEOUT = 0.75
12
12
 
13
13
  class Client
14
14
  include Protocol::Methods
@@ -170,6 +170,34 @@ module Seriamp
170
170
  resp
171
171
  end
172
172
 
173
+ MODEL_NAMES = {
174
+ 'R0177' => 'RX-V1500',
175
+ 'R0178' => 'RX-V2500',
176
+ }.freeze
177
+
178
+ PURE_DIRECT_FIELD = {
179
+ 'R0177' => 28,
180
+ 'R0178' => 126,
181
+ }.freeze
182
+
183
+ INPUT_MODE_R0178 = {
184
+ '0' => 'Auto',
185
+ '2' => 'DTS',
186
+ '4' => 'Analog',
187
+ '5' => 'Analog Only',
188
+ }.freeze
189
+
190
+ SAMPLE_RATE_R0178 = {
191
+ '0' => 'Analog',
192
+ '1' => 32000,
193
+ '2' => 44100,
194
+ '3' => 48000,
195
+ '4' => 64000,
196
+ '5' => 88200,
197
+ '6' => 96000,
198
+ '7' => 'Unknown',
199
+ }.freeze
200
+
173
201
  def do_status
174
202
  resp = nil
175
203
  loop do
@@ -188,15 +216,15 @@ module Seriamp
188
216
  length = payload[6..7].to_i(16)
189
217
  data = payload[8...-2]
190
218
  if data.length != length
191
- raise BadStatus, "Broken status response: expected #{length} bytes, got #{data.length} bytes; concurrent operation on device?"
219
+ raise HandshakeFailure, "Broken status response: expected #{length} bytes, got #{data.length} bytes; concurrent operation on device?"
192
220
  end
193
221
  unless data.start_with?('@E01900')
194
- raise BadStatus, "Broken status response: expected to start with @E01900, actual #{data[0..6]}"
222
+ raise HandshakeFailure, "Broken status response: expected to start with @E01900, actual #{data[0..6]}"
195
223
  end
196
224
  @status_string = data
197
225
  @status = {
198
- # RX-V1500: model R0177
199
226
  model_code: @model_code,
227
+ model_name: MODEL_NAMES[@model_code],
200
228
  firmware_version: @version,
201
229
  system_status: data[7].ord - ZERO_ORD,
202
230
  power: power = data[8].ord - ZERO_ORD,
@@ -236,12 +264,20 @@ module Seriamp
236
264
  sleep: SLEEP_GET.fetch(data[24]),
237
265
  night: night = data[27],
238
266
  night_name: NIGHT_GET.fetch(night),
239
- pure_direct: data[28] == '1',
267
+ pure_direct: data[PURE_DIRECT_FIELD.fetch(@model_code)] == '1',
240
268
  speaker_a: data[29] == '1',
241
269
  speaker_b: data[30] == '1',
242
- format: data[31..32],
243
- sample_rate: data[33..34],
270
+ # 2 positions on RX-Vx700
271
+ #format: data[31..32],
272
+ #sampling: data[33..34],
244
273
  )
274
+ if @model_code == 'R0178'
275
+ @status.update(
276
+ input_mode: INPUT_MODE_R0178.fetch(data[11]),
277
+ sampling: data[32],
278
+ sample_rate: SAMPLE_RATE_R0178.fetch(data[32]),
279
+ )
280
+ end
245
281
  end
246
282
  @status
247
283
  end
@@ -62,20 +62,20 @@ module Seriamp
62
62
  exit 3
63
63
  end
64
64
  when 'power'
65
- which = ARGV.shift&.downcase
65
+ which = args.shift&.downcase
66
66
  if %w(main zone2 zone3).include?(which)
67
67
  method = "set_#{which}_power"
68
- state = Utils.parse_on_off(ARGV.shift)
68
+ state = Utils.parse_on_off(args.shift)
69
69
  else
70
70
  method = 'set_power'
71
71
  state = Utils.parse_on_off(which)
72
72
  end
73
73
  client.public_send(method, state)
74
74
  when 'volume'
75
- which = ARGV.shift
75
+ which = args.shift
76
76
  if %w(main zone2 zone3).include?(which)
77
77
  prefix = "set_#{which}"
78
- value = ARGV.shift
78
+ value = args.shift
79
79
  else
80
80
  prefix = 'set_main'
81
81
  value = which
@@ -95,25 +95,28 @@ module Seriamp
95
95
  p client.get_zone2_volume_text
96
96
  p client.get_zone3_volume_text
97
97
  when 'input'
98
- which = ARGV.shift&.downcase
98
+ which = args.shift&.downcase
99
99
  if %w(main zone2 zone3).include?(which)
100
100
  method = "set_#{which}_input"
101
- input = ARGV.shift
101
+ input = args.shift
102
102
  else
103
103
  method = 'set_main_input'
104
104
  input = which
105
105
  end
106
106
  client.public_send(method, input)
107
107
  when 'program'
108
- value = ARGV.shift.downcase
108
+ value = args.shift.downcase
109
109
  client.set_program(value)
110
110
  when 'pure-direct'
111
- state = Utils.parse_on_off(ARGV.shift)
111
+ state = Utils.parse_on_off(args.shift)
112
112
  client.set_pure_direct(state)
113
113
  when 'status'
114
114
  pp client.last_status
115
- when 'status_string'
116
- puts client.last_status_string
115
+ when 'dev-status'
116
+ status = client.last_status_string
117
+ 0.upto(status.length-1).each do |i|
118
+ puts "%3d %s" % [i, status[i]]
119
+ end
117
120
  when 'test'
118
121
  client.set_power(false)
119
122
  [true, false].each do |main_state|
@@ -1,9 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'seriamp/yamaha/protocol/constants'
4
+
3
5
  module Seriamp
4
6
  module Yamaha
5
7
  module Protocol
6
8
  module Methods
9
+ include Constants
7
10
 
8
11
  # Turns the receiver on or off.
9
12
  #
@@ -87,7 +90,7 @@ module Seriamp
87
90
  end
88
91
 
89
92
  def set_subwoofer_level(level)
90
- dispatch("#{STX}249#{'%02x' % level}#{ETX}")
93
+ system_command("49#{'%02x' % level}")
91
94
  end
92
95
 
93
96
  def get_main_volume_text
@@ -106,7 +109,7 @@ module Seriamp
106
109
  #
107
110
  # @param [ true | false ] state Desired state.
108
111
  def set_pure_direct(state)
109
- dispatch("#{STX}07E8#{state ? '0' : '2'}#{ETX}")
112
+ remote_command("7E8#{state ? '0' : '2'}")
110
113
  end
111
114
 
112
115
  def set_program(value)
data/seriamp.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "seriamp"
5
- spec.version = '0.1.2'
5
+ spec.version = '0.1.4'
6
6
  spec.authors = ['Oleg Pudeyev']
7
7
  spec.email = ['code@olegp.name']
8
8
  spec.summary = %q{Serial control for amplifiers & A/V receivers}
@@ -14,4 +14,8 @@ Gem::Specification.new do |spec|
14
14
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
15
15
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
16
16
  spec.require_paths = ["lib"]
17
+
18
+ spec.add_runtime_dependency 'serialport', '~> 1.0'
19
+
20
+ # Optional dependencies: sinatra for the web apps
17
21
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: seriamp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oleg Pudeyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-27 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2022-11-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: serialport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
13
27
  description: Library for controlling Yamaha A/V receivers and Sonance Sonamp amplifiers
14
28
  via the serial port
15
29
  email: