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.
- checksums.yaml +4 -4
- data/lib/aca-device-modules/version.rb +1 -1
- data/modules/aca/lifter_logic_auto.rb +71 -0
- data/modules/aca/lifter_logic_manual.rb +105 -0
- data/modules/aca/pc_control.rb +111 -111
- data/modules/axis/camera/vapix.rb +10 -3
- data/modules/biamp/nexia.rb +149 -128
- data/modules/bss/blu100.rb +8 -8
- data/modules/chiyu/cyt.rb +6 -1
- data/modules/clipsal/c_bus.rb +233 -235
- data/modules/epson/projector/esc_vp21.rb +232 -232
- data/modules/extron/mixer/dmp44.rb +174 -174
- data/modules/extron/mixer/dmp64.rb +192 -181
- data/modules/extron/switcher/dxp.rb +210 -210
- data/modules/global_cache/gc100.rb +6 -2
- data/modules/kramer/switcher/protocol3000.rb +209 -209
- data/modules/kramer/switcher/vs_hdmi.rb +111 -110
- data/modules/nec/display/all.rb +440 -443
- data/modules/nec/projector/np_series.rb +609 -597
- data/modules/panasonic/camera/he50.rb +1 -1
- data/modules/panasonic/projector/tcp.rb +239 -234
- data/modules/philips/dynalite.rb +196 -0
- data/modules/samsung/displays/md_series.rb +34 -16
- data/modules/screen_technics/connect.rb +53 -53
- data/modules/sony/display/id_talk.rb +275 -275
- data/modules/sony/projector/pj_talk.rb +257 -257
- data/modules/vaddio/camera/clear_view_ptz_telnet.rb +7 -3
- metadata +6 -3
@@ -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
|
-
|
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(:
|
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
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
end
|
31
|
+
|
32
|
+
def on_unload
|
33
|
+
end
|
34
|
+
|
35
|
+
def on_update
|
36
36
|
@id = setting(:display_id) || 0xFF
|
37
|
-
|
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
|
147
|
-
if
|
148
|
-
self[:audio_mute]
|
149
|
-
|
150
|
-
|
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
|
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
|
-
#
|
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
|
-
|
5
|
+
include ::Orchestrator::Constants
|
6
6
|
|
7
7
|
|
8
|
-
|
9
|
-
|
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
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
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
|
-
|
62
|
+
protected
|
63
63
|
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
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
|
-
|
9
|
+
include ::Orchestrator::Constants
|
10
10
|
include ::Orchestrator::Transcoder
|
11
11
|
|
12
|
-
|
13
|
-
|
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
|
-
|
33
|
-
|
32
|
+
on_update
|
33
|
+
end
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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
|
-
|
42
|
-
|
43
|
-
|
41
|
+
def connected
|
42
|
+
@polling_timer = schedule.every('60s', method(:do_poll))
|
43
|
+
end
|
44
44
|
|
45
|
-
|
46
|
-
|
45
|
+
def disconnected
|
46
|
+
@polling_timer.cancel unless @polling_timer.nil?
|
47
47
|
@polling_timer = nil
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
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
|
-
|
233
|
+
bytes = str_to_array(byte_str)
|
234
234
|
|
235
|
-
|
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
|
-
|
241
|
+
return true
|
242
242
|
elsif data.length > bytes[7]
|
243
|
-
|
244
|
-
|
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
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
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
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
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
|
|