aca-device-modules 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +165 -0
- data/README.md +3 -0
- data/aca-device-modules.gemspec +21 -0
- data/lib/aca-device-modules.rb +2 -0
- data/lib/aca-device-modules/engine.rb +8 -0
- data/lib/aca-device-modules/version.rb +3 -0
- data/modules/aca/pc_control.rb +142 -0
- data/modules/axis/camera/vapix.rb +280 -0
- data/modules/biamp/nexia.rb +125 -0
- data/modules/bss/blu100.rb +265 -0
- data/modules/clipsal/c_bus.rb +256 -0
- data/modules/epson/projector/esc_vp21.rb +248 -0
- data/modules/extron/mixer/dmp44.rb +195 -0
- data/modules/extron/mixer/dmp64.rb +212 -0
- data/modules/extron/switcher/dxp.rb +249 -0
- data/modules/global_cache/gc100.rb +167 -0
- data/modules/kramer/switcher/vs_hdmi.rb +143 -0
- data/modules/panasonic/camera/he50.rb +346 -0
- data/modules/panasonic/projector/pj_link.rb +266 -0
- data/modules/samsung/displays/md_series.rb +256 -0
- data/modules/vaddio/camera/clear_view_ptz_telnet.rb +138 -0
- metadata +94 -0
@@ -0,0 +1,346 @@
|
|
1
|
+
module Panasonic; end
|
2
|
+
module Panasonic::Camera; end
|
3
|
+
|
4
|
+
|
5
|
+
class Panasonic::Camera::He50
|
6
|
+
include ::Orchestrator::Constants
|
7
|
+
include ::Orchestrator::Transcoder
|
8
|
+
|
9
|
+
def on_load
|
10
|
+
on_update
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_update
|
14
|
+
defaults({
|
15
|
+
delay: 130, # As per the manual page 8
|
16
|
+
keepalive: false,
|
17
|
+
inactivity_timeout: 1.5, # seconds before closing the connection if no response
|
18
|
+
connect_timeout: 2 # max seconds for the initial connection to the device
|
19
|
+
})
|
20
|
+
|
21
|
+
self[:pan_max] = 0xD2F5
|
22
|
+
self[:pan_min] = 0x2D08
|
23
|
+
self[:pan_center] = 0x7FFF
|
24
|
+
self[:tilt_max] = 0x8E38
|
25
|
+
self[:tilt_min] = 0x5556
|
26
|
+
self[:tilt_center] = 0x7FFF
|
27
|
+
|
28
|
+
self[:joy_left] = 0x01
|
29
|
+
self[:joy_right] = 0x99
|
30
|
+
self[:joy_center] = 0x50
|
31
|
+
|
32
|
+
self[:zoom_max] = 0xFFF
|
33
|
+
self[:zoom_min] = 0x555
|
34
|
+
|
35
|
+
self[:focus_max] = 0xFFF
|
36
|
+
self[:focus_min] = 0x555
|
37
|
+
|
38
|
+
self[:iris_max] = 0xFFF
|
39
|
+
self[:iris_min] = 0x555
|
40
|
+
|
41
|
+
# {near: {zoom: val, pan: val, tilt: val}}
|
42
|
+
@presets = setting(:presets) || {}
|
43
|
+
self[:presets] = @presets.keys
|
44
|
+
end
|
45
|
+
|
46
|
+
def connected
|
47
|
+
schedule.every('60s', method(:do_poll))
|
48
|
+
do_poll
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
RESP = {
|
53
|
+
power: 'p',
|
54
|
+
installation: 'iNS',
|
55
|
+
|
56
|
+
pantilt: 'aPC',
|
57
|
+
joystick: 'pTS',
|
58
|
+
limit: 'lC',
|
59
|
+
|
60
|
+
zoom: /axz|gz/,
|
61
|
+
manual_zoom: 'zS',
|
62
|
+
link_zoom: 'sWZ',
|
63
|
+
|
64
|
+
focus: /axf|gf/,
|
65
|
+
manual_focus: 'fS',
|
66
|
+
auto_focus: 'd1',
|
67
|
+
|
68
|
+
iris: /axi|gi/,
|
69
|
+
auto_iris: 'd3'
|
70
|
+
}
|
71
|
+
LIMITS = {
|
72
|
+
up: 1,
|
73
|
+
down: 2,
|
74
|
+
left: 3,
|
75
|
+
right: 4
|
76
|
+
}
|
77
|
+
LIMITS.merge!(LIMITS.invert)
|
78
|
+
|
79
|
+
|
80
|
+
# Responds with:
|
81
|
+
# 0 == standby
|
82
|
+
# 1 == power on
|
83
|
+
# 3 == powering on
|
84
|
+
def power(state = nil, &blk)
|
85
|
+
state = (is_affirmative?(state) ? 1 : 0) unless state.nil?
|
86
|
+
|
87
|
+
options = {}
|
88
|
+
options[:emit] = blk if blk
|
89
|
+
options[:delay] = 6000 if state
|
90
|
+
|
91
|
+
logger.debug "Camera requested power #{state}"
|
92
|
+
|
93
|
+
req('O', state, :power, options) do |data, resolve|
|
94
|
+
val = extract(:power, data, resolve)
|
95
|
+
if val
|
96
|
+
self[:power] = val.to_i > 0
|
97
|
+
:success
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def installation(pos = nil)
|
103
|
+
pos = (pos.to_sym == :desk ? 0 : 1) if pos
|
104
|
+
|
105
|
+
req('INS', pos, :installation) do |data, resolve|
|
106
|
+
val = extract(:installation, data, resolve)
|
107
|
+
if val
|
108
|
+
self[:installation] = val == '0' ? :desk : :ceiling
|
109
|
+
:success
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def pantilt(pan = nil, tilt = nil)
|
115
|
+
unless pan.nil?
|
116
|
+
pan = in_range(pan.to_i, self[:pan_max], self[:pan_min]).to_s(16).upcase.rjust(4, '0')
|
117
|
+
tilt = in_range(tilt.to_i, self[:tilt_max], self[:tilt_min]).to_s(16).upcase.rjust(4, '0')
|
118
|
+
end
|
119
|
+
|
120
|
+
req('APC', "#{pan}#{tilt}", :pantilt) do |data, resolve|
|
121
|
+
val = extract(:pantilt, data, resolve)
|
122
|
+
if val
|
123
|
+
comp = []
|
124
|
+
val.scan(/.{4}/) { |com| comp << com.to_i(16) }
|
125
|
+
self[:pan] = comp[0]
|
126
|
+
self[:tilt] = comp[1]
|
127
|
+
:success
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Recall a preset from the database
|
133
|
+
def preset(name)
|
134
|
+
values = @presets[name.to_sym]
|
135
|
+
if values
|
136
|
+
pantilt(values[:pan], values[:tilt])
|
137
|
+
zoom(values[:zoom])
|
138
|
+
true
|
139
|
+
else
|
140
|
+
false
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def joystick(pan_speed, tilt_speed)
|
145
|
+
left_max = self[:joy_left]
|
146
|
+
right_max = self[:joy_right]
|
147
|
+
pan_speed = in_range(pan_speed.to_i, right_max, left_max).to_s(16).upcase.rjust(2, '0')
|
148
|
+
tilt_speed = in_range(tilt_speed.to_i, right_max, left_max).to_s(16).upcase.rjust(2, '0')
|
149
|
+
|
150
|
+
is_centered = false
|
151
|
+
if pan_speed == '50' && tilt_speed == '50'
|
152
|
+
is_centered = true
|
153
|
+
end
|
154
|
+
|
155
|
+
options = {}
|
156
|
+
options[:retries] = is_centered ? 1 : 0
|
157
|
+
|
158
|
+
logger.debug("Sending camera: #{pan_speed}#{tilt_speed}");
|
159
|
+
|
160
|
+
req('PTS', "#{pan_speed}#{tilt_speed}", :joystick, options) do |data, resolve|
|
161
|
+
val = extract(:joystick, data, resolve)
|
162
|
+
if val
|
163
|
+
comp = []
|
164
|
+
val.scan(/.{2}/) { |com| comp << com.to_i(16) }
|
165
|
+
self[:joy_pan] = comp[0]
|
166
|
+
self[:joy_tilt] = comp[1]
|
167
|
+
:success
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def limit(direction, state = nil)
|
173
|
+
dir = LIMITS[direction.to_sym]
|
174
|
+
state = (is_affirmative?(set) ? 1 : 0) unless state.nil?
|
175
|
+
|
176
|
+
req('LC', "#{dir}#{state}", :limit) do |data, resolve|
|
177
|
+
val = extract(:limit, data, resolve)
|
178
|
+
if val
|
179
|
+
self[:"limit_#{LIMITS[val[0].to_i]}"] = val[1] == '1'
|
180
|
+
:success
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
def zoom(pos = nil)
|
187
|
+
cmd = 'AXZ'
|
188
|
+
if pos
|
189
|
+
pos = in_range(pos.to_i, self[:zoom_max], self[:zoom_min]).to_s(16).upcase.rjust(3, '0')
|
190
|
+
else
|
191
|
+
cmd = 'GZ'
|
192
|
+
end
|
193
|
+
|
194
|
+
req(cmd, pos, :zoom) do |data, resolve|
|
195
|
+
val = extract(:zoom, data, resolve)
|
196
|
+
if val
|
197
|
+
self[:zoom] = val.to_i(16)
|
198
|
+
:success
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def manual_zoom(speed)
|
204
|
+
speed = in_range(speed.to_i, self[:joy_right], self[:joy_left]).to_s(16).upcase.rjust(3, '0')
|
205
|
+
|
206
|
+
req('Z', speed, :manual_zoom) do |data, resolve|
|
207
|
+
val = extract(:manual_zoom, data, resolve)
|
208
|
+
if val
|
209
|
+
self[:manual_zoom] = val.to_i(16)
|
210
|
+
:success
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def link_zoom(state = nil) # Link pantilt speed to zoom
|
216
|
+
state = (is_affirmative?(state) ? 1 : 0) unless state.nil?
|
217
|
+
|
218
|
+
req('SWZ', state, :link_zoom) do |data, resolve|
|
219
|
+
val = extract(:link_zoom, data, resolve)
|
220
|
+
if val
|
221
|
+
self[:link_zoom] = val == '1'
|
222
|
+
:success
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
|
228
|
+
def focus(pos = nil)
|
229
|
+
cmd = 'AXF'
|
230
|
+
if pos
|
231
|
+
pos = in_range(pos.to_i, self[:focus_max], self[:focus_min]).to_s(16).upcase.rjust(3, '0')
|
232
|
+
else
|
233
|
+
cmd = 'GF'
|
234
|
+
end
|
235
|
+
|
236
|
+
req(cmd, pos, :focus) do |data, resolve|
|
237
|
+
val = extract(:focus, data, resolve)
|
238
|
+
if val
|
239
|
+
self[:focus] = val.to_i(16)
|
240
|
+
:success
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def manual_focus(speed)
|
246
|
+
speed = in_range(speed.to_i, self[:joy_right], self[:joy_left]).to_s(16).upcase.rjust(2, '0')
|
247
|
+
|
248
|
+
req('F', speed, :manual_focus) do |data, resolve|
|
249
|
+
val = extract(:manual_focus, data, resolve)
|
250
|
+
if val
|
251
|
+
self[:manual_focus] = val.to_i(16)
|
252
|
+
:success
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def auto_focus(state = nil)
|
258
|
+
state = (is_affirmative?(state) ? 1 : 0) unless state.nil?
|
259
|
+
|
260
|
+
req('D1', state, :auto_focus) do |data, resolve|
|
261
|
+
val = extract(:auto_focus, data, resolve)
|
262
|
+
if val
|
263
|
+
self[:auto_focus] = val == '1'
|
264
|
+
:success
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
|
270
|
+
def iris(level = nil)
|
271
|
+
cmd = 'AXI'
|
272
|
+
if level
|
273
|
+
level = in_range(level.to_i, self[:iris_max], self[:iris_min]).to_s(16).upcase.rjust(3, '0')
|
274
|
+
else
|
275
|
+
cmd = 'GI'
|
276
|
+
end
|
277
|
+
|
278
|
+
req(cmd, level, :iris) do |data, resolve|
|
279
|
+
val = extract(:iris, data, resolve)
|
280
|
+
if val
|
281
|
+
self[:iris] = val[0..2].to_i(16)
|
282
|
+
if val.length == 4
|
283
|
+
self[:auto_iris] = val == '1'
|
284
|
+
end
|
285
|
+
:success
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
def auto_iris(state = nil)
|
291
|
+
state = (is_affirmative?(state) ? 1 : 0) unless state.nil?
|
292
|
+
|
293
|
+
req('D3', state, :auto_iris) do |data, resolve|
|
294
|
+
val = extract(:auto_iris, data, resolve)
|
295
|
+
if val
|
296
|
+
self[:auto_iris] = val == '1'
|
297
|
+
:success
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
|
303
|
+
protected
|
304
|
+
|
305
|
+
|
306
|
+
def req(cmd, data, name, options = {}, &blk)
|
307
|
+
if data.nil? || (data.respond_to?(:empty?) && data.empty?)
|
308
|
+
options[:delay] = 0
|
309
|
+
options[:priority] = 0 # Actual commands have a higher priority
|
310
|
+
else
|
311
|
+
options[:name] = name
|
312
|
+
end
|
313
|
+
request_string = "/cgi-bin/aw_ptz?cmd=%23#{cmd}#{data}&res=1"
|
314
|
+
get(request_string, options, &blk)
|
315
|
+
|
316
|
+
logger.debug "requesting #{name}: #{request_string}"
|
317
|
+
end
|
318
|
+
|
319
|
+
def extract(name, data, resp)
|
320
|
+
logger.debug "received #{data} for command #{name}"
|
321
|
+
|
322
|
+
body = data[:body]
|
323
|
+
if body[0] == 'e'
|
324
|
+
notify_error(body, 'invalid command sent', data)
|
325
|
+
resp.call(:failed)
|
326
|
+
nil
|
327
|
+
else
|
328
|
+
body.sub(RESP[name], '')
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
def do_poll(*args)
|
333
|
+
power do
|
334
|
+
if self[:power] # only request status if online
|
335
|
+
pantilt
|
336
|
+
zoom
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
def notify_error(err, msg, cmd)
|
342
|
+
cmd = cmd[:request]
|
343
|
+
logger.warn "Camera error response: #{err} - #{msg} for #{cmd[:path]} #{cmd[:query]}"
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
@@ -0,0 +1,266 @@
|
|
1
|
+
module Panasonic; end
|
2
|
+
module Panasonic::Projector; end
|
3
|
+
|
4
|
+
|
5
|
+
require 'digest/md5'
|
6
|
+
|
7
|
+
#
|
8
|
+
# Port: 1024
|
9
|
+
#
|
10
|
+
class Panasonic::Projector::PjLink
|
11
|
+
include ::Orchestrator::Constants
|
12
|
+
include ::Orchestrator::Transcoder
|
13
|
+
|
14
|
+
def on_load
|
15
|
+
# PJLink is slow
|
16
|
+
defaults({
|
17
|
+
timeout: 4000,
|
18
|
+
delay_on_receive: 400
|
19
|
+
})
|
20
|
+
|
21
|
+
config({
|
22
|
+
tokenize: true,
|
23
|
+
delimiter: "\r",
|
24
|
+
wait_ready: 'NTCONTROL'
|
25
|
+
})
|
26
|
+
|
27
|
+
@check_scheduled = false
|
28
|
+
self[:power] = false
|
29
|
+
self[:stable_state] = true # Stable by default (allows manual on and off)
|
30
|
+
self[:input_stable] = true
|
31
|
+
|
32
|
+
# Meta data for inquiring interfaces
|
33
|
+
self[:type] = :projector
|
34
|
+
end
|
35
|
+
|
36
|
+
def on_update
|
37
|
+
end
|
38
|
+
|
39
|
+
def connected
|
40
|
+
@polling_timer = schedule.every('60s', method(:do_poll))
|
41
|
+
end
|
42
|
+
|
43
|
+
def disconnected
|
44
|
+
self[:power] = false
|
45
|
+
|
46
|
+
@polling_timer.cancel unless @polling_timer.nil?
|
47
|
+
@polling_timer = nil
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
#
|
53
|
+
# Power commands
|
54
|
+
#
|
55
|
+
def power(state, opt = nil)
|
56
|
+
self[:stable_state] = false
|
57
|
+
if is_affirmative?(state)
|
58
|
+
self[:power_target] = On
|
59
|
+
do_send(:POWR, 1, {:retries => 10, :name => :power})
|
60
|
+
logger.debug "-- panasonic Proj, requested to power on"
|
61
|
+
do_send('POWR', '?', :name => :power_state)
|
62
|
+
else
|
63
|
+
self[:power_target] = Off
|
64
|
+
do_send(:POWR, 0, {:retries => 10, :name => :power})
|
65
|
+
logger.debug "-- panasonic Proj, requested to power off"
|
66
|
+
do_send('POWR', '?', :name => :power_state)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def power?(options = {}, &block)
|
71
|
+
options[:emit] = block if block_given?
|
72
|
+
options[:name] = :power_state
|
73
|
+
do_send(:POWR, options)
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
#
|
79
|
+
# Input selection
|
80
|
+
#
|
81
|
+
INPUTS = {
|
82
|
+
:hdmi => 31,
|
83
|
+
:hdmi2 => 32,
|
84
|
+
:digital => 33,
|
85
|
+
:miracast => 52
|
86
|
+
}
|
87
|
+
INPUTS.merge!(INPUTS.invert)
|
88
|
+
|
89
|
+
|
90
|
+
def switch_to(input)
|
91
|
+
input = input.to_sym
|
92
|
+
return unless INPUTS.has_key? input
|
93
|
+
|
94
|
+
do_send(:INPT, INPUTS[input], {:retries => 10, :name => :inpt_source})
|
95
|
+
do_send('INPT', '?', {:name => :inpt_query})
|
96
|
+
logger.debug "-- panasonic LCD, requested to switch to: #{input}"
|
97
|
+
|
98
|
+
self[:input] = input # for a responsive UI
|
99
|
+
self[:input_stable] = false
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
#
|
104
|
+
# Mute Audio and Video
|
105
|
+
#
|
106
|
+
def mute
|
107
|
+
logger.debug "-- panasonic Proj, requested to mute"
|
108
|
+
do_send(:AVMT, 31, {:name => :video_mute}) # Audio + Video
|
109
|
+
end
|
110
|
+
|
111
|
+
def unmute
|
112
|
+
logger.debug "-- panasonic Proj, requested to unmute"
|
113
|
+
do_send(:AVMT, 30, {:name => :video_mute})
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
ERRORS = {
|
118
|
+
:ERR1 => '1: Undefined control command'.freeze,
|
119
|
+
:ERR2 => '2: Out of parameter range'.freeze,
|
120
|
+
:ERR3 => '3: Busy state or no-acceptable period'.freeze,
|
121
|
+
:ERR4 => '4: Timeout or no-acceptable period'.freeze,
|
122
|
+
:ERR5 => '5: Wrong data length'.freeze,
|
123
|
+
:ERRA => 'A: Password mismatch'.freeze
|
124
|
+
}
|
125
|
+
|
126
|
+
|
127
|
+
def received(data, resolve, command) # Data is default received as a string
|
128
|
+
logger.debug "panasonic Proj sent: #{data}"
|
129
|
+
|
130
|
+
# This is the ready response
|
131
|
+
if data[0] == ' '
|
132
|
+
@mode = data[1]
|
133
|
+
if @mode == '1'
|
134
|
+
@pass = "#{setting(:username) || 'admin1'}:#{setting(:password) || 'panasonic'}:#{data.strip.split(/\s+/)[-1]}"
|
135
|
+
@pass = Digest::MD5.hexdigest(@hash)
|
136
|
+
end
|
137
|
+
|
138
|
+
:success
|
139
|
+
|
140
|
+
# Error Response
|
141
|
+
elsif data[0] == 'E'
|
142
|
+
error = data.to_sym
|
143
|
+
#self[:last_error] = ERRORS[error] (for error status query)
|
144
|
+
|
145
|
+
# Check for busy or timeout
|
146
|
+
if error == :ERR3 || error == :ERR4
|
147
|
+
logger.warn "Panasonic Proj busy: #{self[:last_error]}"
|
148
|
+
:retry
|
149
|
+
else
|
150
|
+
logger.error "Panasonic Proj error: #{self[:last_error]}"
|
151
|
+
:abort
|
152
|
+
end
|
153
|
+
|
154
|
+
# Success Response
|
155
|
+
else
|
156
|
+
data = data[2..-1].split('=')
|
157
|
+
|
158
|
+
if data[1] = 'OK'
|
159
|
+
return :success
|
160
|
+
else
|
161
|
+
type = data[0][2..-1].to_sym
|
162
|
+
response = data[1].to_i
|
163
|
+
resolve.call(:success)
|
164
|
+
|
165
|
+
case type
|
166
|
+
when :POWR
|
167
|
+
self[:power] = response >= 1 && response != 2
|
168
|
+
self[:warming] = response == 3
|
169
|
+
self[:cooling] = response == 2
|
170
|
+
if response >= 2 && !@check_scheduled && !self[:stable_state]
|
171
|
+
@check_scheduled = true
|
172
|
+
schedule.in('20s') do
|
173
|
+
@check_scheduled = false
|
174
|
+
logger.debug "-- checking panasonic state"
|
175
|
+
power?({:priority => 0}) do
|
176
|
+
state = self[:power]
|
177
|
+
if state != self[:power_target]
|
178
|
+
if self[:power_target] || !self[:cooling]
|
179
|
+
power(self[:power_target])
|
180
|
+
end
|
181
|
+
elsif self[:power_target] && self[:cooling]
|
182
|
+
power(self[:power_target])
|
183
|
+
else
|
184
|
+
self[:stable_state] = true
|
185
|
+
switch_to(self[:input]) if self[:power_target] == On && !self[:input].nil?
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
when :INPT
|
191
|
+
if INPUTS[response].present?
|
192
|
+
self[:input] = INPUTS[response] if self[:input].nil?
|
193
|
+
self[:actual_input] = INPUTS[response]
|
194
|
+
if self[:input] == self[:actual_input]
|
195
|
+
self[:input_stable] = true
|
196
|
+
elsif self[:input_stable] == false
|
197
|
+
schedule.in('5s') do
|
198
|
+
logger.debug "-- forcing panasonic input"
|
199
|
+
switch_to(self[:input]) if self[:input_stable] == false
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
when :AVMT
|
204
|
+
self[:mute] = response == 31 # 10 == video mute off, 11 == video mute, 20 == audio mute off, 21 == audio mute, 30 == AV mute off
|
205
|
+
when :LAMP
|
206
|
+
self[:lamp] = data[1][0..-2].to_i
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
|
213
|
+
|
214
|
+
protected
|
215
|
+
|
216
|
+
|
217
|
+
def do_poll(*args)
|
218
|
+
power?({:priority => 0}) do
|
219
|
+
if self[:power]
|
220
|
+
if self[:stable_state] == false && self[:power_target] == Off
|
221
|
+
power(Off)
|
222
|
+
else
|
223
|
+
self[:stable_state] = true
|
224
|
+
do_send(:INPT, {
|
225
|
+
:name => :inpt_query,
|
226
|
+
:priority => 0
|
227
|
+
})
|
228
|
+
do_send(:AVMT, {
|
229
|
+
:name => :mute_query,
|
230
|
+
:priority => 0
|
231
|
+
})
|
232
|
+
do_send(:LAMP, {
|
233
|
+
:name => :lamp_query,
|
234
|
+
:priority => 0
|
235
|
+
})
|
236
|
+
end
|
237
|
+
elsif self[:stable_state] == false
|
238
|
+
if self[:power_target] == On
|
239
|
+
power(On)
|
240
|
+
else
|
241
|
+
self[:stable_state] = true
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def do_send(command, param = nil, options = {})
|
248
|
+
if param.is_a? Hash
|
249
|
+
options = param
|
250
|
+
param = nil
|
251
|
+
end
|
252
|
+
|
253
|
+
if param.nil?
|
254
|
+
pj = "#{command} ?"
|
255
|
+
else
|
256
|
+
pj = "#{command} #{param}"
|
257
|
+
end
|
258
|
+
|
259
|
+
if @mode == '0'
|
260
|
+
send("00#{pj}\r", options)
|
261
|
+
else
|
262
|
+
send("#{@pass}00#{pj}\r", options)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|