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.
@@ -5,141 +5,162 @@ module Biamp; end
5
5
  # TELNET port 23
6
6
 
7
7
  class Biamp::Nexia
8
- include ::Orchestrator::Constants
8
+ include ::Orchestrator::Constants
9
9
  include ::Orchestrator::Transcoder
10
-
11
- def on_load
12
- self[:fader_min] = -36 # specifically for tonsley
13
- self[:fader_max] = 12
10
+
11
+ def on_load
12
+ self[:fader_min] = -36 # specifically for tonsley
13
+ self[:fader_max] = 12
14
14
 
15
- # max +12
16
- # min -100
15
+ # max +12
16
+ # min -100
17
17
 
18
- config({
19
- tokenize: true,
20
- delimiter: /\xFF\xFE\x01|\r\n/
21
- })
22
- end
23
-
24
- def on_unload
25
- end
26
-
27
- def on_update
28
- end
29
-
30
-
31
- def connected
32
- send("\xFF\xFE\x01") # Echo off
33
- do_send('GETD', 0, 'DEVID')
34
-
35
- @polling_timer = schedule.every('60s') do
36
- do_send('GETD', 0, 'DEVID')
37
- end
38
- end
39
-
40
- def disconnected
41
- @polling_timer.cancel unless @polling_timer.nil?
42
- @polling_timer = nil
43
- end
44
-
45
-
46
- def preset(number)
47
- #
48
- # Recall Device 0 Preset number 1001
49
- # Device Number will always be 0 for Preset strings
50
- # 1001 == minimum preset number
51
- #
52
- do_send('RECALL', 0, 'PRESET', number)
53
- end
18
+ config({
19
+ tokenize: true,
20
+ delimiter: /\xFF\xFE\x01|\r\n/
21
+ })
22
+ end
23
+
24
+ def on_unload
25
+ end
26
+
27
+ def on_update
28
+ end
29
+
30
+
31
+ def connected
32
+ send("\xFF\xFE\x01") # Echo off
33
+ do_send('GETD', 0, 'DEVID')
34
+
35
+ @polling_timer = schedule.every('60s') do
36
+ do_send('GETD', 0, 'DEVID')
37
+ end
38
+ end
39
+
40
+ def disconnected
41
+ @polling_timer.cancel unless @polling_timer.nil?
42
+ @polling_timer = nil
43
+ end
44
+
45
+
46
+ def preset(number)
47
+ #
48
+ # Recall Device 0 Preset number 1001
49
+ # Device Number will always be 0 for Preset strings
50
+ # 1001 == minimum preset number
51
+ #
52
+ do_send('RECALL', 0, 'PRESET', number)
53
+ end
54
54
 
55
- # {1 => [2,3,5], 2 => [2,3,6]}, true
56
- # Supports Matrix and Automixers
57
- def mixer(id, inouts, mute = false)
58
- value = is_affirmative?(mute) ?
55
+ # {1 => [2,3,5], 2 => [2,3,6]}, true
56
+ # Supports Matrix and Automixers
57
+ def mixer(id, inouts, mute = false)
58
+ value = is_affirmative?(mute) ? 1 : 0
59
59
 
60
- if inouts.is_a? Hash
61
- inouts.each_key do |input|
62
- outputs = inouts[input]
63
- outs = outputs.is_a?(Array) ? outputs : [outputs]
60
+ if inouts.is_a? Hash
61
+ inouts.each_key do |input|
62
+ outputs = inouts[input]
63
+ outs = outputs.is_a?(Array) ? outputs : [outputs]
64
64
 
65
- outs.each do |output|
66
- do_send('SETD', self[:device_id], 'MMMUTEXP', id, input, output, value)
67
- end
68
- end
69
- else # assume array (auto-mixer)
70
- inouts.each do |input|
71
- do_send('SETD', self[:device_id], 'AMMUTEXP', id, input, value)
72
- end
73
- end
74
- end
75
-
76
- def fader(fader_id, level, index = 1)
77
- # value range: -100 ~ 12
78
- do_send('SETD', self[:device_id], 'FDRLVL', fader_id, index, level)
79
- end
80
-
81
- def mute(fader_id, val = true, index = 1)
82
- actual = val ? 1 : 0
83
- do_send('SETD', self[:device_id], 'FDRMUTE', fader_id, index, actual)
84
- end
85
-
86
- def unmute(fader_id, index = 1)
87
- mute(fader_id, false, index)
88
- end
65
+ outs.each do |output|
66
+ do_send('SETD', self[:device_id], 'MMMUTEXP', id, input, output, value)
67
+ end
68
+ end
69
+ else # assume array (auto-mixer)
70
+ inouts.each do |input|
71
+ do_send('SETD', self[:device_id], 'AMMUTEXP', id, input, value)
72
+ end
73
+ end
74
+ end
89
75
 
90
- def query_fader(fader_id, index = 1)
91
- send("GET #{self[:device_id]} FDRLVL #{fader_id} #{index} \n") do |data|
92
- if data.start_with?('-ERR')
93
- :abort
94
- else
95
- self[:"fader#{fader_id}_#{index}"] = data.to_i
96
- :success
97
- end
98
- end
99
- end
76
+ FADERS = {
77
+ fader: 'FDRLVL',
78
+ matrix_in: 'MMLVLIN',
79
+ matrix_out: 'MMLVLOUT',
80
+ matrix_crosspoint: 'MMLVLXP'
81
+ }
82
+
83
+ def fader(fader_id, level, index = 1, type = :level_fader)
84
+ fad_type = FADERS[type.to_sym]
100
85
 
101
- def query_mute(fader_id, index = 1)
102
- send("GET #{self[:device_id]} FDRMUTE #{fader_id} #{index} \n") do |data|
103
- if data.start_with?('-ERR')
104
- :abort
105
- else
106
- self[:"fader#{fader_id}_#{index}_mute"] = data.to_i == 1
107
- :success
108
- end
109
- end
110
- end
111
-
112
-
113
- def received(data, resolve, command)
114
- if data.start_with?('-ERR')
115
- logger.debug "Nexia returned #{data} for #{command[:data]}" if command
116
- return :abort
117
- end
118
-
119
- #--> "#SETD 0 FDRLVL 29 1 0.000000 +OK"
120
- data = data.split(' ')
121
- unless data[2].nil?
122
- case data[2].to_sym
123
- when :FDRLVL, :VL
124
- self[:"fader#{data[3]}_#{data[4]}"] = data[5].to_i
125
- when :FDRMUTE
126
- self[:"fader#{data[3]}_#{data[4]}_mute"] = data[5] == "1"
127
- when :DEVID
128
- # "#GETD 0 DEVID 1 "
129
- self[:device_id] = data[-2].to_i
130
- end
131
- end
132
-
133
- return :success
134
- end
135
-
136
-
137
-
138
- private
139
-
140
-
141
- def do_send(*args)
142
- send("#{args.join(' ')} \n")
143
- end
86
+ # value range: -100 ~ 12
87
+ faders = fader_id.is_a?(Array) ? fader_id : [fader_id]
88
+ faders.each do |fad|
89
+ do_send('SETD', self[:device_id], fad_type, fad, index, level)
90
+ end
91
+ end
92
+
93
+ def mute(fader_id, val = true, index = 1)
94
+ actual = val ? 1 : 0
95
+ faders = fader_id.is_a?(Array) ? fader_id : [fader_id]
96
+ faders.each do |fad|
97
+ do_send('SETD', self[:device_id], 'FDRMUTE', fad, index, actual)
98
+ end
99
+ end
100
+
101
+ def unmute(fader_id, index = 1)
102
+ mute(fader_id, false, index)
103
+ end
104
+
105
+ def query_fader(fader_id, index = 1)
106
+ fad = fader_id.is_a?(Array) ? fader_id[0] : fader_id
107
+
108
+ send("GET #{self[:device_id]} FDRLVL #{fad} #{index} \n") do |data|
109
+ if data.start_with?('-ERR')
110
+ :abort
111
+ else
112
+ self[:"fader#{fad}_#{index}"] = data.to_i
113
+ :success
114
+ end
115
+ end
116
+ end
117
+
118
+ def query_mute(fader_id, index = 1)
119
+ fad = fader_id.is_a?(Array) ? fader_id[0] : fader_id
120
+
121
+ send("GET #{self[:device_id]} FDRMUTE #{fad} #{index} \n") do |data|
122
+ if data.start_with?('-ERR')
123
+ :abort
124
+ else
125
+ self[:"fader#{fad}_#{index}_mute"] = data.to_i == 1
126
+ :success
127
+ end
128
+ end
129
+ end
130
+
131
+
132
+ def received(data, resolve, command)
133
+ if data.start_with?('-ERR')
134
+ logger.debug "Nexia returned #{data} for #{command[:data]}" if command
135
+ return :abort
136
+ end
137
+
138
+ #--> "#SETD 0 FDRLVL 29 1 0.000000 +OK"
139
+ data = data.split(' ')
140
+ unless data[2].nil?
141
+ case data[2].to_sym
142
+ when :FDRLVL, :VL
143
+ self[:"fader#{data[3]}_#{data[4]}"] = data[5].to_i
144
+ when :FDRMUTE
145
+ self[:"fader#{data[3]}_#{data[4]}_mute"] = data[5] == "1"
146
+ when :DEVID
147
+ # "#GETD 0 DEVID 1 "
148
+ self[:device_id] = data[-2].to_i
149
+ when :MMLVLIN
150
+ self[:"matrix_in#{data[3]}_#{data[4]}"] = data[5].to_i
151
+ end
152
+ end
153
+
154
+ return :success
155
+ end
156
+
157
+
158
+
159
+ private
160
+
161
+
162
+ def do_send(*args)
163
+ send("#{args.join(' ')} \n")
164
+ end
144
165
  end
145
166
 
@@ -6,7 +6,7 @@ class Bss::Blu100
6
6
  include ::Orchestrator::Constants
7
7
  include ::Orchestrator::Transcoder
8
8
 
9
- def on_load
9
+ def on_load
10
10
  defaults({
11
11
  :wait => false
12
12
  })
@@ -17,14 +17,14 @@ class Bss::Blu100
17
17
  })
18
18
 
19
19
  on_update
20
- end
21
-
22
- def on_unload
23
- end
24
-
25
- def on_update
20
+ end
21
+
22
+ def on_unload
23
+ end
24
+
25
+ def on_update
26
26
  @type_lookup ||= {}
27
- end
27
+ end
28
28
 
29
29
  def connected
30
30
  subscribe_percent(1, 60000)
@@ -30,13 +30,18 @@ class Chiyu::Cyt
30
30
  def on_update
31
31
  end
32
32
 
33
- # No keep alive required as the device polls us
34
33
  def connected
35
34
  do_send(:state)
36
35
  do_send(:auto_report)
36
+
37
+ @polling_timer = schedule.every('60s') do
38
+ do_send(:state)
39
+ end
37
40
  end
38
41
 
39
42
  def disconnected
43
+ @polling_timer.cancel unless @polling_timer.nil?
44
+ @polling_timer = nil
40
45
  end
41
46
 
42
47
 
@@ -3,13 +3,13 @@ module Clipsal; end
3
3
 
4
4
  #
5
5
  # Common Headers
6
- # 0x03 == point - point -multipoint, low pri
7
- # 0x05 == point - multipoint, low pri
8
- # 0x06 == point - point, low pri
6
+ # 0x03 == point - point -multipoint, low pri
7
+ # 0x05 == point - multipoint, low pri
8
+ # 0x06 == point - point, low pri
9
9
  #
10
- # 11xxx110 (x == reserved)
11
- # -- Priority, 11 == high, 00 == low
12
- # --- Destination, 011 = P-P-M, 101 = P-M, 110 = P-P
10
+ # 11xxx110 (x == reserved)
11
+ # -- Priority, 11 == high, 00 == low
12
+ # --- Destination, 011 = P-P-M, 101 = P-M, 110 = P-P
13
13
  #
14
14
  #
15
15
  # Commands are formatted as: \ + Header + 00 + Data + checksum + <cr>
@@ -22,235 +22,233 @@ module Clipsal; end
22
22
 
23
23
 
24
24
  class Clipsal::CBus
25
- include ::Orchestrator::Constants
25
+ include ::Orchestrator::Constants
26
26
  include ::Orchestrator::Transcoder
27
-
28
- def on_load
29
- defaults({
30
- :wait => false
31
- })
32
-
33
- config({
34
- tokenize: true,
35
- delimiter: "\x0D"
36
- })
37
- end
38
-
39
- def on_unload
40
- end
41
-
42
- def on_update
43
-
44
- end
45
-
46
-
47
- def connected
48
- send("|||\r", :wait => false) # Ensure we are in smart mode
49
- @polling_timer = schedule.every('60s') do
50
- logger.debug "-- Polling CBUS"
51
- send("|||\r", :wait => false) # Ensure we are in smart mode
52
- end
53
- end
54
-
55
- def disconnected
56
- @polling_timer.cancel unless @polling_timer.nil?
57
- @polling_timer = nil
58
- end
59
-
60
-
61
- def lighting(group, state, application = 0x38)
62
- group = group & 0xFF
63
- application = application & 0xFF
64
-
65
- command = [0x05, application, 0x00]
66
- if [On, 1, :on, 'on'].include?(state)
67
- state = On
68
- command << 0x79 # Group on
69
- else
70
- state = Off
71
- command << 0x01 # Group off
72
- end
73
- command << group
74
-
75
- self["lighting_group_#{group}"] = state
76
-
77
- do_send(command)
78
- end
79
-
80
-
81
- def lighting_ramp(group, level, rate = 0b0001, application = 0x38)
82
-
83
- #
84
- # rates:
85
- # => 0 == instant
86
- # => 1 == 4sec
87
- # => 2 == 8sec etc
88
- #
89
- rate = ((rate & 0x0F) << 3) | 0b010 # The command is structured as: 0b0 xxxx 010 where xxxx == rate
90
- group = group & 0xFF
91
- level = level & 0xFF
92
- application = application & 0xFF
93
-
94
- lighting_term_ramp(group)
95
- command = [0x05, application, 0x00, rate, group, level]
96
-
97
- do_send(command)
98
- end
99
-
100
-
101
-
102
- def blinds(group, action, application = 0x38)
103
- group = group & 0xFF
104
- application = application & 0xFF
105
-
106
- command = [0x05, application, 0x00]
107
- if is_affirmative?(action)
108
- action = Down
109
- command += [0x1A, group, 0x00]
110
- else
111
- command += [0x02, group]
112
-
113
- if is_negatory?(action)
114
- action = Up
115
- command << 0xFF
116
- else
117
- # Stop (need to confirm this)
118
- command << 0x05
119
- end
120
- end
121
-
122
- do_send(command)
123
- end
124
-
125
-
126
- def trigger(group, action)
127
- action = action.to_i
128
- group = group.to_i
129
-
130
- group = group & 0xFF
131
- action = action & 0xFF
132
- command = [0x05, 0xCA, 0x00, 0x02, group, action]
133
-
134
- self["trigger_group_#{group}"] = action
135
-
136
- do_send(command)
137
- end
138
-
139
-
140
- def trigger_kill(group)
141
- group = group.to_i
142
-
143
- group = group & 0xFF
144
- command = [0x05, 0xCA, 0x00, 0x01, group]
145
- do_send(command)
146
- end
147
-
148
-
149
- def received(data, resolve, command)
150
- # Debug here will sometimes have the \n char
151
- # This is removed by the hex_to_byte function
152
- logger.debug "CBus sent #{data}"
153
-
154
- data = str_to_array(hex_to_byte(data))
155
-
156
- if !check_checksum(data)
157
- logger.debug "CBus checksum failed"
158
- return :failed
159
- end
160
-
161
- # We are only looking at Point -> MultiPoint commands
162
- return if data[0] != 0x05
163
- # 0x03 == Point -> Point -> MultiPoint
164
- # 0x06 == Point -> Point
165
-
166
- application = data[2] # The application being referenced
167
- commands = data[4..-2] # Remove the header + checksum
168
-
169
- while commands.length > 0
170
- current = commands.shift
171
-
172
- case application
173
- when 0xCA # Trigger group
174
- case current
175
- when 0x02 # Trigger Event (ex: 0504CA00 020101 29)
176
- self["trigger_group_#{commands.shift}"] = commands.shift # Action selector
177
- when 0x01 # Trigger Min
178
- self["trigger_group_#{commands.shift}"] = 0
179
- when 0x79 # Trigger Max
180
- self["trigger_group_#{commands.shift}"] = 0xFF
181
- when 0x09 # Indicator Kill (ex: 0504CA00 0901 23)
182
- commands.shift # Group (turns off indicators of all scenes triggered by this group)
183
- else
184
- break # We don't know what data is here
185
- end
186
- when 0x30..0x5F # Lighting group
187
- case current
188
- when 0x01 # Group off (ex: 05043800 0101 0102 0103 0104 7905 33)
189
- self["lighting_group_#{commands.shift}"] = Off
190
- when 0x79 # Group on (ex: 05013800 7905 44)
191
- self["lighting_group_#{commands.shift}"] = On
192
- when 0x02 # Blinds up or stop
193
- group = commands.shift
194
- value = commands.shift
195
- if value == 0xFF
196
- self["blinds_group_#{group}"] = Up
197
- elsif value == 0x05 # Value needs confirmation
198
- self["blinds_group_#{group}"] = :stopped
199
- end
200
- when 0x1A # Blinds down
201
- group = commands.shift
202
- value = commands.shift
203
- self["blinds_group_#{group}"] = Down if value == 0x00
204
- when 0x09 # Terminate Ramp
205
- commands.shift # Group address
206
- else
207
- if (current & 0b10000101) == 0 # Ramp to level (ex: 05013800 0205FF BC)
208
- commands.shift(2) # Group address, level
209
- else
210
- break # We don't know what data is here
211
- end
212
- end
213
- else
214
- break # We haven't programmed this application
215
- end
216
- end
217
-
218
- return :success
219
- end
220
-
221
-
222
- protected
223
-
224
-
225
- def lighting_term_ramp(group)
226
- command = [0x05, 0x38, 0x00, 0x09, group]
227
- do_send(command)
228
- end
229
-
230
-
231
- def checksum(data)
232
- check = 0
233
- data.each do |byte|
234
- check += byte
235
- end
236
- check = check % 0x100
237
- check = ((check ^ 0xFF) + 1) & 0xFF
238
- return check
239
- end
240
-
241
- def check_checksum(data)
242
- check = 0
243
- data.each do |byte|
244
- check += byte
245
- end
246
- return (check % 0x100) == 0x00
247
- end
248
-
249
-
250
- def do_send(command, options = {})
251
- string = byte_to_hex(array_to_str(command << checksum(command))).upcase
252
- send("\\#{string}\r", options)
253
- #logger.debug "CBus module sent #{string}"
254
- end
27
+
28
+ def on_load
29
+ defaults({
30
+ wait: false,
31
+ delay: 100 # NOTE:: maybe too much?
32
+ })
33
+
34
+ config({
35
+ tokenize: true,
36
+ delimiter: "\x0D"
37
+ })
38
+ end
39
+
40
+ def on_unload
41
+ end
42
+
43
+ def on_update
44
+
45
+ end
46
+
47
+
48
+ def connected
49
+ send("|||\r", priority: 99) # Ensure we are in smart mode
50
+ @polling_timer = schedule.every('60s') do
51
+ logger.debug "-- Polling CBUS"
52
+ send("|||\r", priority: 99) # Ensure we are in smart mode
53
+ end
54
+ end
55
+
56
+ def disconnected
57
+ @polling_timer.cancel unless @polling_timer.nil?
58
+ @polling_timer = nil
59
+ end
60
+
61
+
62
+ def lighting(group, state, application = 0x38)
63
+ group = group & 0xFF
64
+ application = application & 0xFF
65
+
66
+ command = [0x05, application, 0x00]
67
+ if [On, 1, :on, 'on'].include?(state)
68
+ state = On
69
+ command << 0x79 # Group on
70
+ else
71
+ state = Off
72
+ command << 0x01 # Group off
73
+ end
74
+ command << group
75
+
76
+ self["lighting_group_#{group}"] = state
77
+
78
+ do_send(command)
79
+ end
80
+
81
+
82
+ def lighting_ramp(group, level, rate = 0b0001, application = 0x38)
83
+
84
+ #
85
+ # rates:
86
+ # => 0 == instant
87
+ # => 1 == 4sec
88
+ # => 2 == 8sec etc
89
+ #
90
+ rate = ((rate & 0x0F) << 3) | 0b010 # The command is structured as: 0b0 xxxx 010 where xxxx == rate
91
+ group = group & 0xFF
92
+ level = level & 0xFF
93
+ application = application & 0xFF
94
+
95
+ lighting_term_ramp(group)
96
+ command = [0x05, application, 0x00, rate, group, level]
97
+
98
+ do_send(command)
99
+ end
100
+
101
+
102
+
103
+ def blinds(group, action, application = 0x38)
104
+ group = group & 0xFF
105
+ application = application & 0xFF
106
+
107
+ command = [0x05, application, 0x00]
108
+ if is_affirmative?(action)
109
+ action = Down
110
+ command += [0x1A, group, 0x00]
111
+ else
112
+ command += [0x02, group]
113
+
114
+ if is_negatory?(action)
115
+ action = Up
116
+ command << 0xFF
117
+ else
118
+ # Stop (need to confirm this)
119
+ command << 0x05
120
+ end
121
+ end
122
+
123
+ do_send(command)
124
+ end
125
+
126
+
127
+ def trigger(group, action)
128
+ group = group.to_i & 0xFF
129
+ action = action.to_i & 0xFF
130
+ command = [0x05, 0xCA, 0x00, 0x02, group, action]
131
+
132
+ self["trigger_group_#{group}"] = action
133
+
134
+ do_send(command)
135
+ end
136
+
137
+
138
+ def trigger_kill(group)
139
+ group = group.to_i
140
+
141
+ group = group & 0xFF
142
+ command = [0x05, 0xCA, 0x00, 0x01, group]
143
+ do_send(command)
144
+ end
145
+
146
+
147
+ def received(data, resolve, command)
148
+ # Debug here will sometimes have the \n char
149
+ # This is removed by the hex_to_byte function
150
+ logger.debug "CBus sent #{data}"
151
+
152
+ data = str_to_array(hex_to_byte(data))
153
+
154
+ if !check_checksum(data)
155
+ logger.debug "CBus checksum failed"
156
+ return :failed
157
+ end
158
+
159
+ # We are only looking at Point -> MultiPoint commands
160
+ return if data[0] != 0x05
161
+ # 0x03 == Point -> Point -> MultiPoint
162
+ # 0x06 == Point -> Point
163
+
164
+ application = data[2] # The application being referenced
165
+ commands = data[4..-2] # Remove the header + checksum
166
+
167
+ while commands.length > 0
168
+ current = commands.shift
169
+
170
+ case application
171
+ when 0xCA # Trigger group
172
+ case current
173
+ when 0x02 # Trigger Event (ex: 0504CA00 020101 29)
174
+ self["trigger_group_#{commands.shift}"] = commands.shift # Action selector
175
+ when 0x01 # Trigger Min
176
+ self["trigger_group_#{commands.shift}"] = 0
177
+ when 0x79 # Trigger Max
178
+ self["trigger_group_#{commands.shift}"] = 0xFF
179
+ when 0x09 # Indicator Kill (ex: 0504CA00 0901 23)
180
+ commands.shift # Group (turns off indicators of all scenes triggered by this group)
181
+ else
182
+ break # We don't know what data is here
183
+ end
184
+ when 0x30..0x5F # Lighting group
185
+ case current
186
+ when 0x01 # Group off (ex: 05043800 0101 0102 0103 0104 7905 33)
187
+ self["lighting_group_#{commands.shift}"] = Off
188
+ when 0x79 # Group on (ex: 05013800 7905 44)
189
+ self["lighting_group_#{commands.shift}"] = On
190
+ when 0x02 # Blinds up or stop
191
+ group = commands.shift
192
+ value = commands.shift
193
+ if value == 0xFF
194
+ self["blinds_group_#{group}"] = Up
195
+ elsif value == 0x05 # Value needs confirmation
196
+ self["blinds_group_#{group}"] = :stopped
197
+ end
198
+ when 0x1A # Blinds down
199
+ group = commands.shift
200
+ value = commands.shift
201
+ self["blinds_group_#{group}"] = Down if value == 0x00
202
+ when 0x09 # Terminate Ramp
203
+ commands.shift # Group address
204
+ else
205
+ if (current & 0b10000101) == 0 # Ramp to level (ex: 05013800 0205FF BC)
206
+ commands.shift(2) # Group address, level
207
+ else
208
+ break # We don't know what data is here
209
+ end
210
+ end
211
+ else
212
+ break # We haven't programmed this application
213
+ end
214
+ end
215
+
216
+ return :success
217
+ end
218
+
219
+
220
+ protected
221
+
222
+
223
+ def lighting_term_ramp(group)
224
+ command = [0x05, 0x38, 0x00, 0x09, group]
225
+ do_send(command)
226
+ end
227
+
228
+
229
+ def checksum(data)
230
+ check = 0
231
+ data.each do |byte|
232
+ check += byte
233
+ end
234
+ check = check % 0x100
235
+ check = ((check ^ 0xFF) + 1) & 0xFF
236
+ return check
237
+ end
238
+
239
+ def check_checksum(data)
240
+ check = 0
241
+ data.each do |byte|
242
+ check += byte
243
+ end
244
+ return (check % 0x100) == 0x00
245
+ end
246
+
247
+
248
+ def do_send(command, options = {})
249
+ string = byte_to_hex(command << checksum(command)).upcase
250
+ send("\\#{string}\r", options)
251
+ #logger.debug "CBus module sent #{string}"
252
+ end
255
253
  end
256
254