sonamp 0.0.4 → 0.0.5
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 +4 -4
- data/LICENSE +23 -0
- data/bin/sonamp +3 -42
- data/lib/sonamp/client.rb +74 -18
- data/lib/sonamp/cmd.rb +63 -0
- data/lib/sonamp/version.rb +1 -1
- data/sonamp.gemspec +2 -2
- metadata +4 -3
- data/.gitignore +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 816d27d5e7d9e1e5c1ab289d18dce3fdddb18a8fa15bb19ca51f776adfe0fdd0
|
4
|
+
data.tar.gz: faffd6868c0c625f8a7ae839cbc00a53f9d1d8d75124c00691c035f18c1af8e5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1335f8bf639400ad932b0672919160b4754c41dbd46dbcd7107145d8147a648b4f29705a3eff322ffb39c21d5c13229e6f622c2885c5a792ad9aba8420566bfe
|
7
|
+
data.tar.gz: 8cbf78ea9632fdefa9d50270890396c3722bbb94654f003fad5746c4e341456f4c66c4cd6d4f5fd7202c1f59dd951afef96aa201079388d8ae818d457c7de63e
|
data/LICENSE
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright (c) 2022 Oleg Pudeyev
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
|
10
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
this list of conditions and the following disclaimer in the documentation
|
12
|
+
and/or other materials provided with the distribution.
|
13
|
+
|
14
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
15
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
16
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
17
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
18
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
19
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
20
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
21
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
22
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
23
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/bin/sonamp
CHANGED
@@ -1,49 +1,10 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
begin
|
4
|
-
require 'sonamp'
|
4
|
+
require 'sonamp/cmd'
|
5
5
|
rescue LoadError
|
6
6
|
$: << File.join(File.dirname(__FILE__), '../lib')
|
7
|
-
require 'sonamp'
|
7
|
+
require 'sonamp/cmd'
|
8
8
|
end
|
9
|
-
require 'optparse'
|
10
|
-
require 'logger'
|
11
|
-
require 'sonamp/utils'
|
12
9
|
|
13
|
-
|
14
|
-
OptionParser.new do |opts|
|
15
|
-
opts.banner = "Usage: sonamp [-d device] command arg..."
|
16
|
-
|
17
|
-
opts.on("-d", "--device DEVICE", "TTY to use (default autodetect)") do |v|
|
18
|
-
options[:device] = v
|
19
|
-
end
|
20
|
-
end.parse!
|
21
|
-
|
22
|
-
logger = Logger.new(STDERR)
|
23
|
-
client = Sonamp::Client.new(options[:device], logger: logger)
|
24
|
-
|
25
|
-
cmd = ARGV.shift
|
26
|
-
unless cmd
|
27
|
-
raise ArgumentError, "No command given"
|
28
|
-
end
|
29
|
-
|
30
|
-
include Sonamp::Utils
|
31
|
-
|
32
|
-
case cmd
|
33
|
-
when 'power'
|
34
|
-
zone = ARGV.shift.to_i
|
35
|
-
state = parse_on_off(ARGV.shift)
|
36
|
-
client.set_zone_power(zone, state)
|
37
|
-
when 'zvol'
|
38
|
-
zone = ARGV.shift.to_i
|
39
|
-
volume = ARGV.shift.to_i
|
40
|
-
client.set_zone_volume(zone, volume)
|
41
|
-
when 'cvol'
|
42
|
-
channel = ARGV.shift.to_i
|
43
|
-
volume = ARGV.shift.to_i
|
44
|
-
client.set_channel_volume(channel, volume)
|
45
|
-
when 'status'
|
46
|
-
client.status
|
47
|
-
else
|
48
|
-
raise ArgumentError, "Unknown command: #{cmd}"
|
49
|
-
end
|
10
|
+
Sonamp::Cmd.new(ARGV).run
|
data/lib/sonamp/client.rb
CHANGED
@@ -43,11 +43,10 @@ module Sonamp
|
|
43
43
|
if zone < 1 || zone > 4
|
44
44
|
raise ArgumentError, "Zone must be between 1 and 4: #{zone}"
|
45
45
|
end
|
46
|
-
|
47
|
-
resp[2...].to_i
|
46
|
+
Integer(dispatch_extract_suffix(":V#{zone}?", 'V'))
|
48
47
|
else
|
49
48
|
dispatch(":VG?", 4).map do |resp|
|
50
|
-
resp
|
49
|
+
Integer(extract_suffix(resp, 'V'))
|
51
50
|
end
|
52
51
|
end
|
53
52
|
end
|
@@ -64,6 +63,10 @@ module Sonamp
|
|
64
63
|
dispatch_assert(cmd, expected)
|
65
64
|
end
|
66
65
|
|
66
|
+
def get_channel_volume(channel = nil)
|
67
|
+
get_channel_value('VC', channel)
|
68
|
+
end
|
69
|
+
|
67
70
|
def set_channel_volume(channel, volume)
|
68
71
|
if channel < 1 || channel > 8
|
69
72
|
raise ArgumentError, "Channel must be between 1 and 4: #{channel}"
|
@@ -80,6 +83,18 @@ module Sonamp
|
|
80
83
|
get_zone_state('M', zone)
|
81
84
|
end
|
82
85
|
|
86
|
+
def get_channel_mute(channel = nil)
|
87
|
+
get_channel_value('MC', channel)
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_channel_front_panel_level(channel = nil)
|
91
|
+
get_channel_value('TVL', channel)
|
92
|
+
end
|
93
|
+
|
94
|
+
def get_zone_fault(zone = nil)
|
95
|
+
get_zone_state('FP', zone)
|
96
|
+
end
|
97
|
+
|
83
98
|
def get_bbe(zone = nil)
|
84
99
|
get_zone_state('BP', zone)
|
85
100
|
end
|
@@ -100,26 +115,35 @@ module Sonamp
|
|
100
115
|
get_zone_state('VTI', zone)
|
101
116
|
end
|
102
117
|
|
118
|
+
def get_firmware_version
|
119
|
+
global_query('VER')
|
120
|
+
end
|
121
|
+
|
122
|
+
def get_temperature
|
123
|
+
Integer(global_query('TP'))
|
124
|
+
end
|
125
|
+
|
103
126
|
def status
|
104
127
|
# Reusing the opened device file makes :VTIG? fail even with a delay
|
105
128
|
# in front.
|
106
129
|
#open_device do
|
107
|
-
p dispatch(':VER?')
|
108
|
-
p dispatch(':TP?')
|
109
|
-
p get_power
|
110
|
-
p dispatch(':FPG?', 4)
|
111
|
-
p get_zone_volume
|
112
|
-
p dispatch(':VCG?', 8)
|
113
|
-
p get_auto_trigger_input
|
114
|
-
sleep 0.1
|
115
|
-
p get_voltage_trigger_input
|
116
|
-
p dispatch(':TVLG?', 8)
|
117
|
-
p get_zone_mute
|
118
|
-
p dispatch(':MCG?', 8)
|
119
|
-
p get_bbe
|
120
|
-
p get_bbe_high_boost
|
121
|
-
p get_bbe_low_boost
|
122
130
|
#end
|
131
|
+
{
|
132
|
+
firmware_version: get_firmware_version,
|
133
|
+
temperature: get_temperature,
|
134
|
+
zone_power: get_zone_power,
|
135
|
+
zone_fault: get_zone_fault,
|
136
|
+
zone_volume: get_zone_volume,
|
137
|
+
channel_volume: get_channel_volume,
|
138
|
+
zone_mute: get_zone_mute,
|
139
|
+
channel_mute: get_channel_mute,
|
140
|
+
bbe: get_bbe,
|
141
|
+
bbe_high_boost: get_bbe_high_boost,
|
142
|
+
bbe_low_boost: get_bbe_low_boost,
|
143
|
+
auto_trigger_input: get_auto_trigger_input,
|
144
|
+
voltage_trigger_input: get_voltage_trigger_input,
|
145
|
+
channel_front_panel_level: get_channel_front_panel_level,
|
146
|
+
}
|
123
147
|
end
|
124
148
|
|
125
149
|
private
|
@@ -158,6 +182,22 @@ module Sonamp
|
|
158
182
|
end
|
159
183
|
end
|
160
184
|
|
185
|
+
def extract_suffix(resp, expected_prefix)
|
186
|
+
unless resp[0..expected_prefix.length-1] == expected_prefix
|
187
|
+
raise "Unexpected response: expected #{expected_prefix}..., actual #{resp}"
|
188
|
+
end
|
189
|
+
resp[expected_prefix.length..]
|
190
|
+
end
|
191
|
+
|
192
|
+
def dispatch_extract_suffix(cmd, expected_prefix)
|
193
|
+
resp = dispatch(cmd)
|
194
|
+
extract_suffix(resp, expected_prefix)
|
195
|
+
end
|
196
|
+
|
197
|
+
def global_query(cmd)
|
198
|
+
dispatch_extract_suffix(":#{cmd}?", cmd)
|
199
|
+
end
|
200
|
+
|
161
201
|
def read_line(f, cmd)
|
162
202
|
f.readline.strip.tap do |resp|
|
163
203
|
if resp == 'ERR'
|
@@ -181,5 +221,21 @@ module Sonamp
|
|
181
221
|
end
|
182
222
|
end
|
183
223
|
end
|
224
|
+
|
225
|
+
def get_channel_value(cmd_prefix, channel)
|
226
|
+
if channel
|
227
|
+
if channel < 1 || channel > 8
|
228
|
+
raise ArgumentError, "Channel must be between 1 and 8: #{channel}"
|
229
|
+
end
|
230
|
+
Integer(dispatch_extract_suffix(":#{cmd_prefix}#{channel}?", "#{cmd_prefix}#{channel}"))
|
231
|
+
else
|
232
|
+
index = 1
|
233
|
+
dispatch(":#{cmd_prefix}G?", 8).map do |resp|
|
234
|
+
Integer(extract_suffix(resp, "#{cmd_prefix}#{index}")).tap do
|
235
|
+
index += 1
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
184
240
|
end
|
185
241
|
end
|
data/lib/sonamp/cmd.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'logger'
|
3
|
+
require 'sonamp/utils'
|
4
|
+
require 'sonamp/client'
|
5
|
+
|
6
|
+
module Sonamp
|
7
|
+
class Cmd
|
8
|
+
def initialize(args)
|
9
|
+
options = {}
|
10
|
+
OptionParser.new do |opts|
|
11
|
+
opts.banner = "Usage: sonamp [-d device] command arg..."
|
12
|
+
|
13
|
+
opts.on("-d", "--device DEVICE", "TTY to use (default autodetect)") do |v|
|
14
|
+
options[:device] = v
|
15
|
+
end
|
16
|
+
end.parse!(args)
|
17
|
+
|
18
|
+
@options = options
|
19
|
+
|
20
|
+
@logger = Logger.new(STDERR)
|
21
|
+
@client = Sonamp::Client.new(options[:device], logger: @logger)
|
22
|
+
|
23
|
+
@args = args
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_reader :args
|
27
|
+
|
28
|
+
def run
|
29
|
+
cmd = args.shift
|
30
|
+
unless cmd
|
31
|
+
raise ArgumentError, "No command given"
|
32
|
+
end
|
33
|
+
|
34
|
+
case cmd
|
35
|
+
when 'off'
|
36
|
+
client.set_zone_power(1, false)
|
37
|
+
client.set_zone_power(2, false)
|
38
|
+
client.set_zone_power(3, false)
|
39
|
+
client.set_zone_power(4, false)
|
40
|
+
when 'power'
|
41
|
+
zone = args.shift.to_i
|
42
|
+
state = Utils.parse_on_off(ARGV.shift)
|
43
|
+
client.set_zone_power(zone, state)
|
44
|
+
when 'zvol'
|
45
|
+
zone = args.shift.to_i
|
46
|
+
volume = ARGV.shift.to_i
|
47
|
+
client.set_zone_volume(zone, volume)
|
48
|
+
when 'cvol'
|
49
|
+
channel = args.shift.to_i
|
50
|
+
volume = args.shift.to_i
|
51
|
+
client.set_channel_volume(channel, volume)
|
52
|
+
when 'status'
|
53
|
+
pp client.status
|
54
|
+
else
|
55
|
+
raise ArgumentError, "Unknown command: #{cmd}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
attr_reader :client
|
62
|
+
end
|
63
|
+
end
|
data/lib/sonamp/version.rb
CHANGED
data/sonamp.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |spec|
|
4
4
|
spec.name = "sonamp"
|
5
|
-
spec.version = '0.0.
|
5
|
+
spec.version = '0.0.5'
|
6
6
|
spec.authors = ['Oleg Pudeyev']
|
7
7
|
spec.email = ['code@olegp.name']
|
8
8
|
spec.summary = %q{Sonance Sonamp Amplifier Serial Control Interface}
|
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.homepage = "https://github.com/p/sonamp-ruby"
|
11
11
|
spec.license = "MIT"
|
12
12
|
|
13
|
-
spec.files = `git ls-files -z`.split("\x0")
|
13
|
+
spec.files = `git ls-files -z [A-Z]* bin lib *.gemspec`.split("\x0")
|
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"]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sonamp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
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-10-
|
11
|
+
date: 2022-10-27 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Library for controlling Sonance Sonamp 875D & 875D MkII amplifiers via
|
14
14
|
the serial port
|
@@ -20,12 +20,13 @@ executables:
|
|
20
20
|
extensions: []
|
21
21
|
extra_rdoc_files: []
|
22
22
|
files:
|
23
|
-
-
|
23
|
+
- LICENSE
|
24
24
|
- bin/sonamp
|
25
25
|
- bin/sonamp-web
|
26
26
|
- lib/sonamp.rb
|
27
27
|
- lib/sonamp/app.rb
|
28
28
|
- lib/sonamp/client.rb
|
29
|
+
- lib/sonamp/cmd.rb
|
29
30
|
- lib/sonamp/utils.rb
|
30
31
|
- lib/sonamp/version.rb
|
31
32
|
- sonamp.gemspec
|
data/.gitignore
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
*.gem
|