aca-device-modules 1.0.4 → 1.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.
@@ -0,0 +1,196 @@
1
+ module Philips; end
2
+
3
+
4
+ class Philips::Dynalite
5
+ include ::Orchestrator::Constants
6
+ include ::Orchestrator::Transcoder
7
+
8
+
9
+ def on_load
10
+ #
11
+ # Setup constants
12
+ #
13
+ defaults({
14
+ wait: false,
15
+ delay: 0.4
16
+ })
17
+
18
+ config({
19
+ tokenize: true,
20
+ indicator: "\x1C",
21
+ msg_length: 7 # length - indicator
22
+ })
23
+ end
24
+
25
+ def connected
26
+ @polling_timer = schedule.every('1m') do
27
+ logger.debug "-- Dynalite Maintaining Connection"
28
+ get_current_preset(1) # preset for area 1
29
+ end
30
+ end
31
+
32
+ def disconnected
33
+ #
34
+ # Disconnected may be called without calling connected
35
+ # Hence the check if timer is nil here
36
+ #
37
+ @polling_timer.cancel unless @polling_timer.nil?
38
+ @polling_timer = nil
39
+ end
40
+
41
+
42
+ #
43
+ # Arguments: preset_number, area_number, fade_time in millisecond
44
+ # Trigger for CBUS module compatibility
45
+ #
46
+ def trigger(area, number, fade = 1000)
47
+ # 0,1,2,3 then a,b,c,d for 4,5,6,7
48
+ self[:"area#{area}"] = number
49
+ area = area.to_i
50
+ number = number.to_i
51
+ fade = (fade / 10).to_i
52
+
53
+ number = number - 1
54
+ bank = number / 8
55
+ number = number - (bank * 8)
56
+
57
+ if number > 3
58
+ number = number - 4 + 0x0A
59
+ end
60
+ #high fade #join (currently all in group)
61
+ command = [0x1c, area & 0xFF, fade & 0xFF, number & 0xFF, (fade >> 8) & 0xFF, bank, 0xFF]
62
+
63
+ do_send(command)
64
+ end
65
+ # Seems to be an undocument trigger command with opcode 65
66
+ # -- not sure how fade works with it..
67
+
68
+ def get_current_preset(area)
69
+ command = [0x1c, area.to_i & 0xFF, 0, 0x63, 0, 0, 0xFF]
70
+ do_send(command)
71
+ end
72
+
73
+ def save_preset(area)
74
+ command = [0x1c, area.to_i & 0xFF, 0, 0x66, 0, 0, 0xFF]
75
+ do_send(command)
76
+ end
77
+
78
+
79
+ def light_level(area, level, channel = 0xFF, fade = 1000)
80
+ cmd = 0x71
81
+
82
+ # Command changes based on the length of the fade time
83
+ if fade <= 25500
84
+ fade = (fade / 100).to_i
85
+ elsif fade < 255000
86
+ cmd = 0x72
87
+ fade = (fade / 1000).to_i
88
+ else
89
+ cmd = 0x73
90
+ fade = in_range((fade / 60000).to_i, 22, 1)
91
+ end
92
+
93
+ # Levels
94
+ #0x01 == 100%
95
+ #0xFF == 0%
96
+ level = 0xFF - level.to_i # Inverse
97
+ level = in_range(level, 0xFF, 1)
98
+
99
+ command = [0x1c, area & 0xFF, channel & 0xFF, cmd, level, fade & 0xFF, 0xFF]
100
+ do_send(command)
101
+ end
102
+
103
+ def stop_fading(area, channel = 0xFF)
104
+ command = [0x1c, area.to_i & 0xFF, channel.to_i & 0xFF, 0x76, 0, 0, 0xFF]
105
+ do_send(command)
106
+ end
107
+
108
+ def stop_all_fading(area)
109
+ command = [0x1c, area.to_i & 0xFF, 0, 0x7A, 0, 0, 0xFF]
110
+ do_send(command)
111
+ end
112
+
113
+
114
+ def get_light_level(area, channel = 0xFF)
115
+ # area, channel, cmd, join
116
+ do_send([0x1c, area.to_i & 0xFF, channel.to_i & 0xFF, 0x61, 0, 0, 0xFF])
117
+ end
118
+
119
+
120
+ def increment_area_level(area)
121
+ do_send([0x1c, area.to_i & 0xFF, 0x64, 6, 0, 0, 0xFF])
122
+ end
123
+
124
+
125
+ def decrement_area_level(area)
126
+ do_send([0x1c, area.to_i & 0xFF, 0x64, 5, 0, 0, 0xFF])
127
+ end
128
+
129
+
130
+
131
+ def received(data, resolve, command)
132
+ logger.debug "from dynalite 0x#{byte_to_hex(data)}--"
133
+
134
+ data = str_to_array(data)
135
+
136
+ case data[2]
137
+ # current preset selected response
138
+ when 0, 1, 2, 3, 10, 11, 12, 13
139
+
140
+ # 0-3, A-D == preset 1..8
141
+ number = data[2]
142
+ number -= 0x0A + 4 if number > 3
143
+
144
+ # Data 4 represets the preset offset or bank
145
+ number += data[4] * 8 + 1
146
+ self[:"area#{data[0]}"] = number
147
+
148
+ # alternative preset response
149
+ when 0x62
150
+ self[:"area#{data[0]}"] = data[1] + 1
151
+
152
+ # level response (area or channel)
153
+ when 0x60
154
+ level = data[3]
155
+ level = 0 if level <= 1
156
+ level = 0xFF - level # Inverse
157
+
158
+ if data[1] == 0xFF # Area (all channels)
159
+ self[:"area#{data[0]}_level"] = level
160
+ else
161
+ self[:"area#{data[0]}_chan#{data[1]}_level"] = level
162
+ end
163
+ end
164
+
165
+ :success
166
+ end
167
+
168
+
169
+ protected
170
+
171
+
172
+ def do_send(command, options = {})
173
+ #
174
+ # build checksum
175
+ #
176
+ check = 0
177
+ command.each do |byte|
178
+ check = check + byte
179
+ end
180
+ check -= 1
181
+ check = ~check
182
+ check = "%x" % check
183
+ check = check[-2, 2]
184
+ check = check.to_i(16)
185
+
186
+ #
187
+ # Add checksum to command
188
+ command << check
189
+ command = array_to_str(command)
190
+
191
+ send(command, options)
192
+
193
+ logger.debug "to dynalite: 0x#{byte_to_hex(command)}--"
194
+ end
195
+ end
196
+
@@ -8,7 +8,7 @@ class Samsung::Displays::MdSeries
8
8
 
9
9
  #
10
10
  # Control system events
11
- def on_load
11
+ def on_load
12
12
  on_update
13
13
 
14
14
  self[:volume_min] = 0
@@ -19,7 +19,7 @@ class Samsung::Displays::MdSeries
19
19
  tokenize: proc {
20
20
  ::UV::AbstractTokenizer.new({
21
21
  indicator: "\xAA",
22
- callback: method(:check_checksum)
22
+ callback: method(:check_length)
23
23
  })
24
24
  }
25
25
  })
@@ -27,14 +27,14 @@ class Samsung::Displays::MdSeries
27
27
  # Meta data for inquiring interfaces
28
28
  self[:type] = :lcd
29
29
  self[:input_stable] = true
30
- end
31
-
32
- def on_unload
33
- end
34
-
35
- def on_update
30
+ end
31
+
32
+ def on_unload
33
+ end
34
+
35
+ def on_update
36
36
  @id = setting(:display_id) || 0xFF
37
- end
37
+ end
38
38
 
39
39
 
40
40
  #
@@ -143,15 +143,19 @@ class Samsung::Displays::MdSeries
143
143
 
144
144
  #
145
145
  # Emulate mute
146
- def mute
147
- if not self[:audio_mute]
148
- self[:audio_mute] = true
149
- self[:previous_volume] = self[:volume] || 50
150
- volume 0
146
+ def mute_audio(val = true)
147
+ if is_affirmative? val
148
+ if not self[:audio_mute]
149
+ self[:audio_mute] = true
150
+ self[:previous_volume] = self[:volume] || 50
151
+ volume 0
152
+ end
153
+ else
154
+ unmute_audio
151
155
  end
152
156
  end
153
157
 
154
- def unmute
158
+ def unmute_audio
155
159
  if self[:audio_mute]
156
160
  self[:audio_mute] = false
157
161
  volume self[:previous_volume]
@@ -220,7 +224,7 @@ class Samsung::Displays::MdSeries
220
224
  end
221
225
  end
222
226
 
223
- # Called by the Abstract Tokenizer
227
+ # Currently not used. We could check it if we like :)
224
228
  def check_checksum(byte_str)
225
229
  response = str_to_array(byte_str)
226
230
  check = 0
@@ -230,6 +234,20 @@ class Samsung::Displays::MdSeries
230
234
  response[-1] == check
231
235
  end
232
236
 
237
+ # Called by the Abstract Tokenizer
238
+ def check_length(byte_str)
239
+ response = str_to_array(byte_str)
240
+ return false if response.length <= 3
241
+
242
+ len = response[2] + 4 # (data length + header and checksum)
243
+
244
+ if response.length >= len
245
+ return len
246
+ else
247
+ return false
248
+ end
249
+ end
250
+
233
251
  # Called by do_send to create a checksum
234
252
  def checksum(command)
235
253
  check = 0
@@ -2,72 +2,72 @@ module ScreenTechnics; end
2
2
 
3
3
 
4
4
  class ScreenTechnics::Connect
5
- include ::Orchestrator::Constants
5
+ include ::Orchestrator::Constants
6
6
 
7
7
 
8
- def on_load
9
- defaults({
8
+ def on_load
9
+ defaults({
10
10
  delay: 2000,
11
11
  keepalive: false,
12
12
  inactivity_timeout: 1.5, # seconds before closing the connection if no response
13
13
  connect_timeout: 2 # max seconds for the initial connection to the device
14
14
  })
15
15
 
16
- self[:state] = :up
17
- end
18
-
19
- def on_update
20
- end
21
-
22
- def connected
23
- end
24
-
25
- def state(new_state, index = 1)
26
- if is_affirmative?(new_state)
27
- down(index)
28
- else
29
- up(index)
30
- end
31
- end
16
+ self[:state] = :up
17
+ end
18
+
19
+ def on_update
20
+ end
21
+
22
+ def connected
23
+ end
24
+
25
+ def state(new_state, index = 1)
26
+ if is_affirmative?(new_state)
27
+ down(index)
28
+ else
29
+ up(index)
30
+ end
31
+ end
32
32
 
33
- def down(index = 1)
34
- stop(index)
35
- do_send({
36
- state: :down,
37
- body: "Down#{index}=Down",
38
- name: :"position#{index}",
39
- index: index
40
- })
41
- end
33
+ def down(index = 1)
34
+ stop(index)
35
+ do_send({
36
+ state: :down,
37
+ body: "Down#{index}=Down",
38
+ name: :"position#{index}",
39
+ index: index
40
+ })
41
+ end
42
42
 
43
- def up(index = 1)
44
- stop(index)
45
- do_send({
46
- state: :up,
47
- body: "Up#{index}=Up",
48
- name: :"position#{index}",
49
- index: index
50
- })
51
- end
43
+ def up(index = 1)
44
+ stop(index)
45
+ do_send({
46
+ state: :up,
47
+ body: "Up#{index}=Up",
48
+ name: :"position#{index}",
49
+ index: index
50
+ })
51
+ end
52
52
 
53
- def stop(index = 1)
54
- do_send({
55
- body: "Stop#{index}=Stop",
56
- name: :"stop#{index}",
57
- priority: 99
58
- })
59
- end
53
+ def stop(index = 1)
54
+ do_send({
55
+ body: "Stop#{index}=Stop",
56
+ name: :"stop#{index}",
57
+ priority: 99
58
+ })
59
+ end
60
60
 
61
61
 
62
- protected
62
+ protected
63
63
 
64
64
 
65
- def do_send(options)
66
- state = options.delete(:state)
67
- index = options.delete(:index)
68
- post('/ADirectControl.html', options) do
69
- self[:"screen#{index}"] = state if state
70
- :success
71
- end
72
- end
65
+ def do_send(options)
66
+ state = options.delete(:state)
67
+ index = options.delete(:index)
68
+ post('/ADirectControl.html', options) do
69
+ self[:"screen#{index}"] = state if state
70
+ :success
71
+ end
72
+ end
73
73
  end
@@ -6,11 +6,11 @@ module Sony::Display; end
6
6
  # Port: 53484
7
7
  #
8
8
  class Sony::Display::IdTalk
9
- include ::Orchestrator::Constants
9
+ include ::Orchestrator::Constants
10
10
  include ::Orchestrator::Transcoder
11
11
 
12
- def on_load
13
- self[:brightness_min] = 0x00
12
+ def on_load
13
+ self[:brightness_min] = 0x00
14
14
  self[:brightness_max] = 0x64
15
15
  self[:contrast_min] = 0x00
16
16
  self[:contrast_max] = 0x64
@@ -29,298 +29,298 @@ class Sony::Display::IdTalk
29
29
  }
30
30
  })
31
31
 
32
- on_update
33
- end
32
+ on_update
33
+ end
34
34
 
35
- def on_update
36
- # Default community value is SONY - can be changed in displays settings
37
- @community = str_to_array(setting(:community) || 'SONY')
38
- end
39
-
35
+ def on_update
36
+ # Default community value is SONY - can be changed in displays settings
37
+ @community = str_to_array(setting(:community) || 'SONY')
38
+ end
39
+
40
40
 
41
- def connected
42
- @polling_timer = schedule.every('60s', method(:do_poll))
43
- end
41
+ def connected
42
+ @polling_timer = schedule.every('60s', method(:do_poll))
43
+ end
44
44
 
45
- def disconnected
46
- @polling_timer.cancel unless @polling_timer.nil?
45
+ def disconnected
46
+ @polling_timer.cancel unless @polling_timer.nil?
47
47
  @polling_timer = nil
48
- end
49
-
50
-
51
-
52
- #
53
- # Power commands
54
- #
55
- def power(state, opt = nil)
56
- if is_affirmative?(state)
57
- do_send(:power, 1)
58
- logger.debug "-- sony display requested to power on"
59
- else
60
- do_send(:power, 0)
61
- logger.debug "-- sony display requested to power off"
62
- end
63
-
64
- # Request status update
65
- power?
66
- end
67
-
68
- def power?(options = {}, &block)
69
- options[:emit] = block if block_given?
70
- options[:priority] = 0
71
- do_send(:power, options)
72
- end
73
-
74
-
75
-
76
- #
77
- # Input selection
78
- #
79
- INPUTS = {
80
- :vga => 0x08,
81
- :dvi => 0x20,
82
- :hdmi => 0x44,
83
- :hdmi2 => 0x84,
84
- :hdmi3 => 0x85
85
- }
86
- INPUTS.merge!(INPUTS.invert)
87
-
88
-
89
- def switch_to(input)
90
- input = input.to_sym
91
- return unless INPUTS.has_key? input
92
-
93
- do_send(:input, INPUTS[input])
94
- logger.debug "-- sony display, requested to switch to: #{input}"
95
-
96
- input?
97
- end
98
-
99
- def input?
100
- do_send(:input, {:priority => 0})
101
- end
102
-
103
-
104
- #
105
- # Mute Audio and Video
106
- #
107
- def mute
108
- logger.debug "-- sony display, requested to mute"
109
- do_send(:mute, 1)
110
- mute?
111
- end
112
-
113
- def unmute
114
- logger.debug "-- sony display, requested to unmute"
115
- do_send(:mute, 0)
116
- mute?
117
- end
118
-
119
- def mute?
120
- do_send(:mute, {:priority => 0})
121
- end
122
-
123
- def audio_mute
124
- logger.debug "-- sony display, requested to mute"
125
- do_send(:audio_mute, 1)
126
- audio_mute?
127
- end
128
-
129
- def audio_unmute
130
- logger.debug "-- sony display, requested to unmute"
131
- do_send(:audio_mute, 0)
132
- audio_mute?
133
- end
134
-
135
- def audio_mute?
136
- do_send(:audio_mute, {:priority => 0})
137
- end
138
-
139
-
140
- #
141
- # Automatically creates a callable function for each command
142
- # http://blog.jayfields.com/2007/10/ruby-defining-class-methods.html
143
- # http://blog.jayfields.com/2008/02/ruby-dynamically-define-method.html
144
- #
145
- [:contrast, :brightness, :volume].each do |command|
146
- # Query command
147
- define_method :"#{command}?" do
148
- do_send(command, {:priority => 0})
149
- end
150
-
151
- # Set value command
152
- define_method command do |level|
153
- do_send(command, level)
154
- __send__(:"#{command}?")
155
- end
156
- end
157
-
158
-
159
-
160
- ERRORS = {
161
- :ERR1 => '1: Undefined control command'.freeze,
162
- :ERR2 => '2: Out of parameter range'.freeze,
163
- :ERR3 => '3: Busy state or no-acceptable period'.freeze,
164
- :ERR4 => '4: Timeout or no-acceptable period'.freeze,
165
- :ERR5 => '5: Wrong data length'.freeze,
166
- :ERRA => 'A: Password mismatch'.freeze
167
- }
168
-
169
- RESP = {
170
- 0x00 => :success,
171
- 0x01 => :limit_over,
172
- 0x02 => :limit_under,
173
- 0x03 => :cancelled
174
- }
175
-
176
-
177
- def received(byte_str, resolve, command) # Data is default received as a string
178
- logger.debug "sony display sent: 0x#{byte_to_hex(data)}"
179
-
180
- data = str_to_array(byte_str)
181
- idt_command = data[5..6]
182
- resp = data[8..-1]
183
-
184
- if data[4] == 0x01
185
- # resp is now equal to the unit control codes
186
-
187
- type = RESP[resp[1]]
188
-
189
- case type
190
- when :success
191
- if resp.length > 3 && command
192
- # This is a request response
193
- cmd = command[:name]
194
-
195
- case cmd
196
- when :power, :audio_mute, :mute
197
- self[cmd] = resp[3] == 0x01
198
- when :input
199
- self[cmd] = INPUTS[resp[3]]
200
- when :signal_status
201
- self[cmd] = resp[3] != 0x01
202
- when :contrast, :brightness, :volume
203
- self[cmd] = resp[3]
204
- end
205
- end
206
- return :success
207
- when :limit_over, :limit_under
208
- warning = "sony display sent a value that was #{type}"
209
- warning += " for command #{command[:name]}" if command
210
-
211
- logger.warn warning
212
-
213
- return :abort
214
- when :cancelled
215
- # Attempt the request again
216
- return :retry
217
- end
218
-
219
- else
220
- # Command failed.. value == error code
221
- return :abort
222
- end
223
- end
224
-
225
-
226
-
227
- protected
228
-
229
-
230
- # Called by the Abstract Tokenizer to confirm we have the
231
- # whole message.
48
+ end
49
+
50
+
51
+
52
+ #
53
+ # Power commands
54
+ #
55
+ def power(state, opt = nil)
56
+ if is_affirmative?(state)
57
+ do_send(:power, 1)
58
+ logger.debug "-- sony display requested to power on"
59
+ else
60
+ do_send(:power, 0)
61
+ logger.debug "-- sony display requested to power off"
62
+ end
63
+
64
+ # Request status update
65
+ power?
66
+ end
67
+
68
+ def power?(options = {}, &block)
69
+ options[:emit] = block if block_given?
70
+ options[:priority] = 0
71
+ do_send(:power, options)
72
+ end
73
+
74
+
75
+
76
+ #
77
+ # Input selection
78
+ #
79
+ INPUTS = {
80
+ :vga => 0x08,
81
+ :dvi => 0x20,
82
+ :hdmi => 0x44,
83
+ :hdmi2 => 0x84,
84
+ :hdmi3 => 0x85
85
+ }
86
+ INPUTS.merge!(INPUTS.invert)
87
+
88
+
89
+ def switch_to(input)
90
+ input = input.to_sym
91
+ return unless INPUTS.has_key? input
92
+
93
+ do_send(:input, INPUTS[input])
94
+ logger.debug "-- sony display, requested to switch to: #{input}"
95
+
96
+ input?
97
+ end
98
+
99
+ def input?
100
+ do_send(:input, {:priority => 0})
101
+ end
102
+
103
+
104
+ #
105
+ # Mute Audio and Video
106
+ #
107
+ def mute
108
+ logger.debug "-- sony display, requested to mute"
109
+ do_send(:mute, 1)
110
+ mute?
111
+ end
112
+
113
+ def unmute
114
+ logger.debug "-- sony display, requested to unmute"
115
+ do_send(:mute, 0)
116
+ mute?
117
+ end
118
+
119
+ def mute?
120
+ do_send(:mute, {:priority => 0})
121
+ end
122
+
123
+ def mute_audio
124
+ logger.debug "-- sony display, requested to mute audio"
125
+ do_send(:audio_mute, 1)
126
+ audio_mute?
127
+ end
128
+
129
+ def unmute_audio
130
+ logger.debug "-- sony display, requested to unmute audio"
131
+ do_send(:audio_mute, 0)
132
+ audio_mute?
133
+ end
134
+
135
+ def audio_mute?
136
+ do_send(:audio_mute, {:priority => 0})
137
+ end
138
+
139
+
140
+ #
141
+ # Automatically creates a callable function for each command
142
+ # http://blog.jayfields.com/2007/10/ruby-defining-class-methods.html
143
+ # http://blog.jayfields.com/2008/02/ruby-dynamically-define-method.html
144
+ #
145
+ [:contrast, :brightness, :volume].each do |command|
146
+ # Query command
147
+ define_method :"#{command}?" do
148
+ do_send(command, {:priority => 0})
149
+ end
150
+
151
+ # Set value command
152
+ define_method command do |level|
153
+ do_send(command, level)
154
+ __send__(:"#{command}?")
155
+ end
156
+ end
157
+
158
+
159
+
160
+ ERRORS = {
161
+ :ERR1 => '1: Undefined control command'.freeze,
162
+ :ERR2 => '2: Out of parameter range'.freeze,
163
+ :ERR3 => '3: Busy state or no-acceptable period'.freeze,
164
+ :ERR4 => '4: Timeout or no-acceptable period'.freeze,
165
+ :ERR5 => '5: Wrong data length'.freeze,
166
+ :ERRA => 'A: Password mismatch'.freeze
167
+ }
168
+
169
+ RESP = {
170
+ 0x00 => :success,
171
+ 0x01 => :limit_over,
172
+ 0x02 => :limit_under,
173
+ 0x03 => :cancelled
174
+ }
175
+
176
+
177
+ def received(byte_str, resolve, command) # Data is default received as a string
178
+ logger.debug "sony display sent: 0x#{byte_to_hex(data)}"
179
+
180
+ data = str_to_array(byte_str)
181
+ idt_command = data[5..6]
182
+ resp = data[8..-1]
183
+
184
+ if data[4] == 0x01
185
+ # resp is now equal to the unit control codes
186
+
187
+ type = RESP[resp[1]]
188
+
189
+ case type
190
+ when :success
191
+ if resp.length > 3 && command
192
+ # This is a request response
193
+ cmd = command[:name]
194
+
195
+ case cmd
196
+ when :power, :audio_mute, :mute
197
+ self[cmd] = resp[3] == 0x01
198
+ when :input
199
+ self[cmd] = INPUTS[resp[3]]
200
+ when :signal_status
201
+ self[cmd] = resp[3] != 0x01
202
+ when :contrast, :brightness, :volume
203
+ self[cmd] = resp[3]
204
+ end
205
+ end
206
+ return :success
207
+ when :limit_over, :limit_under
208
+ warning = "sony display sent a value that was #{type}"
209
+ warning += " for command #{command[:name]}" if command
210
+
211
+ logger.warn warning
212
+
213
+ return :abort
214
+ when :cancelled
215
+ # Attempt the request again
216
+ return :retry
217
+ end
218
+
219
+ else
220
+ # Command failed.. value == error code
221
+ return :abort
222
+ end
223
+ end
224
+
225
+
226
+
227
+ protected
228
+
229
+
230
+ # Called by the Abstract Tokenizer to confirm we have the
231
+ # whole message.
232
232
  def check_complete(byte_str)
233
- bytes = str_to_array(byte_str)
233
+ bytes = str_to_array(byte_str)
234
234
 
235
- # Min message length is 8 bytes
235
+ # Min message length is 8 bytes
236
236
  return false if bytes.length < 8
237
237
 
238
238
  # Check we have the data
239
239
  data = bytes[8..-1]
240
240
  if data.length == bytes[7]
241
- return true
241
+ return true
242
242
  elsif data.length > bytes[7]
243
- # Let the tokeniser know we only want the following number of bytes
244
- return 7 + bytes[7]
243
+ # Let the tokeniser know we only want the following number of bytes
244
+ return 7 + bytes[7]
245
245
  end
246
246
 
247
247
  # Still waiting on data
248
248
  return false
249
249
  end
250
-
251
-
252
- def do_poll(*args)
253
- power?({:priority => 0}) do
254
- if self[:power]
255
- input?
256
- mute?
257
- audio_mute?
258
- volume?
259
- do_send(:signal_status, {:priority => 0})
260
- end
261
- end
262
- end
263
-
264
- # Constants as per manual page 18
265
- # version, category
266
- IdTalk_Header = [0x02, 0x10]
267
-
268
- # Unit protocol as per manual page 21
269
- # Dedicated unit protocol
270
- IdTalk_Type = [0xF1, 0x00]
271
-
272
-
273
- # category, command
274
- COMMANDS = {
275
- power: [0x00, 0x00],
276
- input: [0x00, 0x01],
277
- audio_mute: [0x00, 0x03],
278
- signal_status: [0x00, 0x75],
279
- mute: [0x00, 0x8D],
280
-
281
- contrast: [0x10, 0x00],
282
- brightness: [0x10, 0x01],
283
- volume: [0x10, 0x30]
284
- }
285
- COMMANDS.merge!(COMMANDS.invert)
286
-
287
-
288
- def build_checksum(command)
289
- check = 0
250
+
251
+
252
+ def do_poll(*args)
253
+ power?({:priority => 0}) do
254
+ if self[:power]
255
+ input?
256
+ mute?
257
+ audio_mute?
258
+ volume?
259
+ do_send(:signal_status, {:priority => 0})
260
+ end
261
+ end
262
+ end
263
+
264
+ # Constants as per manual page 18
265
+ # version, category
266
+ IdTalk_Header = [0x02, 0x10]
267
+
268
+ # Unit protocol as per manual page 21
269
+ # Dedicated unit protocol
270
+ IdTalk_Type = [0xF1, 0x00]
271
+
272
+
273
+ # category, command
274
+ COMMANDS = {
275
+ power: [0x00, 0x00],
276
+ input: [0x00, 0x01],
277
+ audio_mute: [0x00, 0x03],
278
+ signal_status: [0x00, 0x75],
279
+ mute: [0x00, 0x8D],
280
+
281
+ contrast: [0x10, 0x00],
282
+ brightness: [0x10, 0x01],
283
+ volume: [0x10, 0x30]
284
+ }
285
+ COMMANDS.merge!(COMMANDS.invert)
286
+
287
+
288
+ def build_checksum(command)
289
+ check = 0
290
290
  command.each do |byte|
291
291
  check = (check + byte) & 0xFF
292
292
  end
293
293
  [check]
294
- end
295
-
296
-
297
- def do_send(command, param = nil, options = {})
298
- # Check for missing params
299
- if param.is_a? Hash
300
- options = param
301
- param = nil
302
- end
303
-
304
- # Control + Mode
305
- if param.nil?
306
- options[:name] = command
307
- cmd = [0x83] + COMMANDS[command] + [0xFF, 0xFF]
308
- else
309
- options[:name] = :"#{command}_cmd"
310
- type = [0x8C] + COMMANDS[command]
311
- if !param.is_a?(Array)
312
- param = [param]
313
- end
314
- data = [param.length + 1] + param
315
- cmd = type + data
316
- end
317
-
318
- cmd = cmd + build_checksum(cmd)
319
-
320
- # Build the IDTalk header # set request every time?
321
- idt_cmd = IdTalk_Header + @community + [0x00] + IdTalk_Type + [cmd.length] + cmd
322
-
323
- send(idt_cmd, options)
324
- end
294
+ end
295
+
296
+
297
+ def do_send(command, param = nil, options = {})
298
+ # Check for missing params
299
+ if param.is_a? Hash
300
+ options = param
301
+ param = nil
302
+ end
303
+
304
+ # Control + Mode
305
+ if param.nil?
306
+ options[:name] = command
307
+ cmd = [0x83] + COMMANDS[command] + [0xFF, 0xFF]
308
+ else
309
+ options[:name] = :"#{command}_cmd"
310
+ type = [0x8C] + COMMANDS[command]
311
+ if !param.is_a?(Array)
312
+ param = [param]
313
+ end
314
+ data = [param.length + 1] + param
315
+ cmd = type + data
316
+ end
317
+
318
+ cmd = cmd + build_checksum(cmd)
319
+
320
+ # Build the IDTalk header # set request every time?
321
+ idt_cmd = IdTalk_Header + @community + [0x00] + IdTalk_Type + [cmd.length] + cmd
322
+
323
+ send(idt_cmd, options)
324
+ end
325
325
  end
326
326