aca-device-modules 1.0.4 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,7 +12,7 @@ class Panasonic::Camera::He50
12
12
 
13
13
  def on_update
14
14
  defaults({
15
- delay: 130, # As per the manual page 8
15
+ delay: 150, # As per the manual page 8
16
16
  keepalive: false,
17
17
  inactivity_timeout: 1.5, # seconds before closing the connection if no response
18
18
  connect_timeout: 2 # max seconds for the initial connection to the device
@@ -2,249 +2,254 @@ module Panasonic; end
2
2
  module Panasonic::Projector; end
3
3
 
4
4
 
5
+ # Default Web UI Access
6
+ # Username: admin1
7
+ # Password: panasonic
8
+
9
+
5
10
  require 'digest/md5'
6
11
 
7
12
  #
8
13
  # Port: 1024
9
14
  #
10
15
  class Panasonic::Projector::Tcp
11
- include ::Orchestrator::Constants
16
+ include ::Orchestrator::Constants
12
17
  include ::Orchestrator::Transcoder
13
18
 
14
- def on_load
15
- # Response time is slow
16
- defaults({
17
- timeout: 2000,
18
- delay_on_receive: 1000
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
-
31
- # Meta data for inquiring interfaces
32
- self[:type] = :projector
33
-
34
- # The projector drops the connection when there is no activity
35
- schedule.every('60s') do
36
- power?({:priority => 0})
37
- end
38
- end
39
-
40
- def on_update
41
- end
42
-
43
- def connected
44
- end
45
-
46
- def disconnected
47
- end
48
-
49
-
50
- COMMANDS = {
51
- power_on: :PON,
52
- power_off: :POF,
53
- power_query: :QPW,
54
- freeze: :OFZ,
55
- input: :IIS,
56
- mute: :OSH,
57
- lamp: :"Q$S"
58
- }
59
- COMMANDS.merge!(COMMANDS.invert)
60
-
61
-
62
-
63
- #
64
- # Power commands
65
- #
66
- def power(state, opt = nil)
67
- self[:stable_state] = false
68
- if is_affirmative?(state)
69
- self[:power_target] = On
70
- do_send(:power_on, {:retries => 10, :name => :power, delay_on_receive: 8000})
71
- logger.debug "-- panasonic Proj, requested to power on"
72
- do_send(:lamp)
73
- else
74
- self[:power_target] = Off
75
- do_send(:power_off, {:retries => 10, :name => :power, delay_on_receive: 8000})
76
- logger.debug "-- panasonic Proj, requested to power off"
77
- do_send(:lamp)
78
- end
79
- end
80
-
81
- def power?(options = {}, &block)
82
- options[:emit] = block if block_given?
83
- do_send(:lamp, options)
84
- end
85
-
86
-
87
-
88
- #
89
- # Input selection
90
- #
91
- INPUTS = {
92
- :hdmi => :HD1,
93
- :hdmi2 => :HD2,
94
- :vga => :RG1,
95
- :vga2 => :RG2,
96
- :miracast => :MC1
97
- }
98
- INPUTS.merge!(INPUTS.invert)
99
-
100
-
101
- def switch_to(input)
102
- input = input.to_sym
103
- return unless INPUTS.has_key? input
104
-
105
- # Projector doesn't automatically unmute
106
- unmute if self[:mute]
107
-
108
- do_send(:input, INPUTS[input], {:retries => 10, delay_on_receive: 2000})
109
- logger.debug "-- panasonic LCD, requested to switch to: #{input}"
110
-
111
- self[:input] = input # for a responsive UI
112
- end
113
-
114
-
115
- #
116
- # Mute Audio and Video
117
- #
118
- def mute(val = true)
119
- actual = val ? 1 : 0
120
- logger.debug "-- panasonic Proj, requested to mute"
121
- do_send(:mute, actual) # Audio + Video
122
- end
123
-
124
- def unmute
125
- logger.debug "-- panasonic Proj, requested to unmute"
126
- do_send(:mute, 0)
127
- end
128
-
129
-
130
- ERRORS = {
131
- :ERR1 => '1: Undefined control command'.freeze,
132
- :ERR2 => '2: Out of parameter range'.freeze,
133
- :ERR3 => '3: Busy state or no-acceptable period'.freeze,
134
- :ERR4 => '4: Timeout or no-acceptable period'.freeze,
135
- :ERR5 => '5: Wrong data length'.freeze,
136
- :ERRA => 'A: Password mismatch'.freeze,
137
- :ER401 => '401: Command cannot be executed'.freeze,
138
- :ER402 => '402: Invalid parameter is sent'.freeze
139
- }
140
-
141
-
142
- def received(data, resolve, command) # Data is default received as a string
143
- logger.debug "panasonic Proj sent: #{data}"
144
-
145
- # This is the ready response
146
- if data[0] == ' '
147
- @mode = data[1]
148
- if @mode == '1'
149
- @pass = "#{setting(:username) || 'admin1'}:#{setting(:password) || 'panasonic'}:#{data.strip.split(/\s+/)[-1]}"
150
- @pass = Digest::MD5.hexdigest(@pass)
151
- end
152
-
153
- else
154
- data = data[2..-1]
155
-
156
- # Error Response
157
- if data[0] == 'E'
158
- error = data.to_sym
159
- self[:last_error] = ERRORS[error]
160
-
161
- # Check for busy or timeout
162
- if error == :ERR3 || error == :ERR4
163
- logger.warn "Panasonic Proj busy: #{self[:last_error]}"
164
- return :retry
165
- else
166
- logger.error "Panasonic Proj error: #{self[:last_error]}"
167
- return :abort
168
- end
169
- end
19
+ def on_load
20
+ # Response time is slow
21
+ defaults({
22
+ timeout: 2000,
23
+ delay_on_receive: 1000
24
+ })
25
+
26
+ config({
27
+ tokenize: true,
28
+ delimiter: "\r",
29
+ wait_ready: 'NTCONTROL'
30
+ })
31
+
32
+ @check_scheduled = false
33
+ self[:power] = false
34
+ self[:stable_state] = true # Stable by default (allows manual on and off)
35
+
36
+ # Meta data for inquiring interfaces
37
+ self[:type] = :projector
38
+
39
+ # The projector drops the connection when there is no activity
40
+ schedule.every('60s') do
41
+ power?({:priority => 0}) if self[:connected]
42
+ end
43
+ end
44
+
45
+ def on_update
46
+ end
47
+
48
+ def connected
49
+ end
50
+
51
+ def disconnected
52
+ end
53
+
54
+
55
+ COMMANDS = {
56
+ power_on: :PON,
57
+ power_off: :POF,
58
+ power_query: :QPW,
59
+ freeze: :OFZ,
60
+ input: :IIS,
61
+ mute: :OSH,
62
+ lamp: :"Q$S"
63
+ }
64
+ COMMANDS.merge!(COMMANDS.invert)
65
+
66
+
67
+
68
+ #
69
+ # Power commands
70
+ #
71
+ def power(state, opt = nil)
72
+ self[:stable_state] = false
73
+ if is_affirmative?(state)
74
+ self[:power_target] = On
75
+ do_send(:power_on, {:retries => 10, :name => :power, delay_on_receive: 8000})
76
+ logger.debug "-- panasonic Proj, requested to power on"
77
+ do_send(:lamp)
78
+ else
79
+ self[:power_target] = Off
80
+ do_send(:power_off, {:retries => 10, :name => :power, delay_on_receive: 8000})
81
+ logger.debug "-- panasonic Proj, requested to power off"
82
+ do_send(:lamp)
83
+ end
84
+ end
85
+
86
+ def power?(options = {}, &block)
87
+ options[:emit] = block if block_given?
88
+ do_send(:lamp, options)
89
+ end
90
+
91
+
92
+
93
+ #
94
+ # Input selection
95
+ #
96
+ INPUTS = {
97
+ :hdmi => :HD1,
98
+ :hdmi2 => :HD2,
99
+ :vga => :RG1,
100
+ :vga2 => :RG2,
101
+ :miracast => :MC1
102
+ }
103
+ INPUTS.merge!(INPUTS.invert)
104
+
105
+
106
+ def switch_to(input)
107
+ input = input.to_sym
108
+ return unless INPUTS.has_key? input
109
+
110
+ # Projector doesn't automatically unmute
111
+ unmute if self[:mute]
112
+
113
+ do_send(:input, INPUTS[input], {:retries => 10, delay_on_receive: 2000})
114
+ logger.debug "-- panasonic LCD, requested to switch to: #{input}"
115
+
116
+ self[:input] = input # for a responsive UI
117
+ end
118
+
119
+
120
+ #
121
+ # Mute Audio and Video
122
+ #
123
+ def mute(val = true)
124
+ actual = val ? 1 : 0
125
+ logger.debug "-- panasonic Proj, requested to mute"
126
+ do_send(:mute, actual) # Audio + Video
127
+ end
128
+
129
+ def unmute
130
+ logger.debug "-- panasonic Proj, requested to unmute"
131
+ do_send(:mute, 0)
132
+ end
133
+
134
+
135
+ ERRORS = {
136
+ :ERR1 => '1: Undefined control command'.freeze,
137
+ :ERR2 => '2: Out of parameter range'.freeze,
138
+ :ERR3 => '3: Busy state or no-acceptable period'.freeze,
139
+ :ERR4 => '4: Timeout or no-acceptable period'.freeze,
140
+ :ERR5 => '5: Wrong data length'.freeze,
141
+ :ERRA => 'A: Password mismatch'.freeze,
142
+ :ER401 => '401: Command cannot be executed'.freeze,
143
+ :ER402 => '402: Invalid parameter is sent'.freeze
144
+ }
145
+
146
+
147
+ def received(data, resolve, command) # Data is default received as a string
148
+ logger.debug "panasonic Proj sent: #{data}"
149
+
150
+ # This is the ready response
151
+ if data[0] == ' '
152
+ @mode = data[1]
153
+ if @mode == '1'
154
+ @pass = "#{setting(:username) || 'admin1'}:#{setting(:password) || 'panasonic'}:#{data.strip.split(/\s+/)[-1]}"
155
+ @pass = Digest::MD5.hexdigest(@pass)
156
+ end
157
+
158
+ else
159
+ data = data[2..-1]
160
+
161
+ # Error Response
162
+ if data[0] == 'E'
163
+ error = data.to_sym
164
+ self[:last_error] = ERRORS[error]
165
+
166
+ # Check for busy or timeout
167
+ if error == :ERR3 || error == :ERR4
168
+ logger.warn "Panasonic Proj busy: #{self[:last_error]}"
169
+ return :retry
170
+ else
171
+ logger.error "Panasonic Proj error: #{self[:last_error]}"
172
+ return :abort
173
+ end
174
+ end
170
175
 
171
176
  resp = data.split(':')
172
- cmd = COMMANDS[resp[0].to_sym]
173
- val = resp[1]
174
-
175
- case cmd
176
- when :power_on
177
- self[:power] = true
178
- when :power_off
179
- self[:power] = false
180
- when :power_query
181
- self[:power] = val.to_i == 1
182
- when :freeze
183
- self[:frozen] = val.to_i == 1
184
- when :input
185
- self[:input] = INPUTS[val.to_sym]
186
- when :mute
187
- self[:mute] = val.to_i == 1
188
- else
189
- if command && command[:name] == :lamp
190
- ival = resp[0].to_i
191
- self[:power] = ival == 1 || ival == 2
192
- self[:warming] = ival == 1
193
- self[:cooling] = ival == 3
194
-
195
- if (self[:warming] || self[:cooling]) && !@check_scheduled && !self[:stable_state]
196
- @check_scheduled = true
197
- schedule.in('13s') do
198
- @check_scheduled = false
199
- logger.debug "-- checking panasonic state"
200
- power?({:priority => 0}) do
201
- state = self[:power]
202
- if state != self[:power_target]
203
- if self[:power_target] || !self[:cooling]
204
- power(self[:power_target])
205
- end
206
- elsif self[:power_target] && self[:cooling]
207
- power(self[:power_target])
208
- else
209
- self[:stable_state] = true
210
- switch_to(self[:input]) if self[:power_target] == On && !self[:input].nil?
211
- end
212
- end
213
- end
214
- end
215
- end
216
- end
217
- end
218
-
219
- :success
220
- end
221
-
222
-
223
- protected
224
-
225
-
226
- def do_send(command, param = nil, options = {})
227
- if param.is_a? Hash
228
- options = param
229
- param = nil
230
- end
231
-
232
- # Default to the command name if name isn't set
233
- options[:name] = command unless options[:name]
234
-
235
- if param.nil?
236
- pj = "#{COMMANDS[command]}"
237
- else
238
- pj = "#{COMMANDS[command]}:#{param}"
239
- end
240
-
241
- if @mode == '0'
242
- send("00#{pj}\r", options)
243
- else
244
- send("#{@pass}00#{pj}\r", options)
245
- end
246
-
247
- nil
248
- end
177
+ cmd = COMMANDS[resp[0].to_sym]
178
+ val = resp[1]
179
+
180
+ case cmd
181
+ when :power_on
182
+ self[:power] = true
183
+ when :power_off
184
+ self[:power] = false
185
+ when :power_query
186
+ self[:power] = val.to_i == 1
187
+ when :freeze
188
+ self[:frozen] = val.to_i == 1
189
+ when :input
190
+ self[:input] = INPUTS[val.to_sym]
191
+ when :mute
192
+ self[:mute] = val.to_i == 1
193
+ else
194
+ if command && command[:name] == :lamp
195
+ ival = resp[0].to_i
196
+ self[:power] = ival == 1 || ival == 2
197
+ self[:warming] = ival == 1
198
+ self[:cooling] = ival == 3
199
+
200
+ if (self[:warming] || self[:cooling]) && !@check_scheduled && !self[:stable_state]
201
+ @check_scheduled = true
202
+ schedule.in('13s') do
203
+ @check_scheduled = false
204
+ logger.debug "-- checking panasonic state"
205
+ power?({:priority => 0}) do
206
+ state = self[:power]
207
+ if state != self[:power_target]
208
+ if self[:power_target] || !self[:cooling]
209
+ power(self[:power_target])
210
+ end
211
+ elsif self[:power_target] && self[:cooling]
212
+ power(self[:power_target])
213
+ else
214
+ self[:stable_state] = true
215
+ switch_to(self[:input]) if self[:power_target] == On && !self[:input].nil?
216
+ end
217
+ end
218
+ end
219
+ end
220
+ end
221
+ end
222
+ end
223
+
224
+ :success
225
+ end
226
+
227
+
228
+ protected
229
+
230
+
231
+ def do_send(command, param = nil, options = {})
232
+ if param.is_a? Hash
233
+ options = param
234
+ param = nil
235
+ end
236
+
237
+ # Default to the command name if name isn't set
238
+ options[:name] = command unless options[:name]
239
+
240
+ if param.nil?
241
+ pj = "#{COMMANDS[command]}"
242
+ else
243
+ pj = "#{COMMANDS[command]}:#{param}"
244
+ end
245
+
246
+ if @mode == '0'
247
+ send("00#{pj}\r", options)
248
+ else
249
+ send("#{@pass}00#{pj}\r", options)
250
+ end
251
+
252
+ nil
253
+ end
249
254
  end
250
255