Class: Xap::Schema::XapBscDevice
- Defined in:
- lib/xap/schema/xap_bsc_device.rb
Overview
Represents an xAP BSC Device. See the xAP Basic Status and Control Schema. www.xapautomation.org/index.php?title=Basic_Status_and_Control_Schema
Instance Attribute Summary
Attributes inherited from XapDevice
Instance Method Summary collapse
-
#add_endpoint(ep) ⇒ Object
Adds a new endpoint hash to the list of endpoints, generating an xAPBSC.info message if the addition is successful.
-
#find_free_uid ⇒ Object
Finds and returns the lowest-available endpoint UID, or nil if there are no free endpoint IDs.
-
#get_display_text(endpoint) ⇒ Object
Returns the DisplayText field of the endpoint with the given name.
-
#get_level(endpoint) ⇒ Object
Returns the Level field of the endpoint with the given name.
-
#get_state(endpoint) ⇒ Object
Returns the State field of the endpoint with the given name.
-
#get_text(endpoint) ⇒ Object
Returns the Text field of the endpoint with the given name.
-
#get_uid(endpoint) ⇒ Object
Returns the UID for the endpoint with the given name, or nil if no such endpoint exists.
-
#handler=(handler) ⇒ Object
Assigns the handler that owns this device, then sends the initial state of all input and output blocks as xAPBSC.info messages.
-
#initialize(address, uid, endpoints, interval = 5) ⇒ XapBscDevice
constructor
Initializes an XapBscDevice with the given address, uid.
-
#receive_message(msg) ⇒ Object
Called when a message targeting this device’s address is received.
-
#remove_endpoint(ep) ⇒ Object
Removes the given endpoint, which may be the endpoint hash or name.
-
#set_address(address) ⇒ Object
Sets the xAP address of this virtual device, then sends an xAPBSC.info message for all endpoints.
-
#set_display_text(endpoint, text) ⇒ Object
Sets the DisplayText field of the endpoint with the given name.
-
#set_level(endpoint, level) ⇒ Object
Sets the Level field of the endpoint with the given name.
-
#set_state(endpoint, state) ⇒ Object
Sets the State field of the endpoint with the given name.
-
#set_text(endpoint, text) ⇒ Object
Sets the Text field of the endpoint with the given name.
-
#uid=(uid) ⇒ Object
Sets the xAP UID of this virtual device, then sends an xAPBSC.info message for all endpoints.
-
#uid_endpoint(uid) ⇒ Object
Returns the endpoint having the given UID, if any.
Methods inherited from XapDevice
Constructor Details
#initialize(address, uid, endpoints, interval = 5) ⇒ XapBscDevice
Initializes an XapBscDevice with the given address, uid. Endpoints is an array of hashes containing :State, :Level, :Text, and/or optionally :DisplayText. :State should be a boolean value or nil, :Level should be an array of [numerator, denominator], and :Text and :DisplayText should be Strings. Each input and output block must also have an :endpoint key that contains the endpoint name for the given block and may include a :uid key that contains an integer from 1 to 254. Endpoint names and UIDs must be unique within this device. Output hashes (i.e. those endpoints that can be changed via xAP) are identified by including a :callback key that is a proc to be called with the endpoint hash when any of the output endpoint’s attributes are changed by an incoming xAP message.
See add_endpoint for a summary of endpoint fields.
Example:
XapBscDevice.new XapAddress.new(‘vendor’, ‘dev’, ‘hostname’), Xap.random_uid, [ { :endpoint => ‘Input 1’, :uid => 1, :State => true }, { :endpoint => ‘Output 1’, :State => true, :callback => proc { |ep| puts ‘Output 1’ } } ]
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/xap/schema/xap_bsc_device.rb', line 31 def initialize address, uid, endpoints, interval = 5 super address, uid, interval # TODO: Make endpoints a hash, with what is currently the # :endpoint field as the hash key, then store the hash key back # into the hash (will simplify calls to XapBscDevice.new, so # the user can type => instead of :endpoint) @input_count = 0 @output_count = 0 @endpoints = {} # Mapping from endpoint name to endpoint hash @uids = [] @outputs = [] # Array containing only output endpoints to simplify handling command messages endpoints.each do |ep| add_endpoint ep end end |
Instance Method Details
#add_endpoint(ep) ⇒ Object
Adds a new endpoint hash to the list of endpoints, generating an xAPBSC.info message if the addition is successful. The endpoint’s name must be unique. UID collision will result in an exception being raised. If the UID is not specified, the lowest available UID will be used.
Summary of endpoint fields: :endpoint - Name of endpoint - mandatory, must be unique when downcased, String :uid - UID of endpoint - optional, must be unique, Fixnum 1-254 :callback - Output change callback - mandatory for outputs, may be nil :State - On/off/? state - mandatory according to xAP BSC spec :Level - numerator / denominator - optional :Text - Stream text - optional (mutually exclusive with :Level according to xAP BSC spec) :DisplayText - UI display text - optional
Example: add_endpoint { :endpoint => ‘Input 1’, :uid => 4, :State => false, :Level => [ 0, 30 ] }
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/xap/schema/xap_bsc_device.rb', line 153 def add_endpoint ep unless ep.include?(:endpoint) && ep.include?(:State) && (!ep.include?(:uid) || ep[:uid].is_a?(Fixnum)) raise 'An endpoint is missing one or more required fields (:endpoint, :State).' end raise "Duplicate endpoint name #{ep[:endpoint]}." if @endpoints.include? ep[:endpoint].downcase ep[:uid] ||= find_free_uid raise "Duplicate UID #{ep[:uid]}." if @uids[ep[:uid]] # TODO: Additional verification of :Level, :Text, and :DisplayText if ep.include? :callback @output_count = @output_count + 1 @outputs << ep else @input_count = @input_count + 1 end @endpoints[ep[:endpoint].downcase] = ep @uids[ep[:uid]] = ep send_info ep if @handler end |
#find_free_uid ⇒ Object
Finds and returns the lowest-available endpoint UID, or nil if there are no free endpoint IDs.
195 196 197 198 199 200 |
# File 'lib/xap/schema/xap_bsc_device.rb', line 195 def find_free_uid for idx in 1..254 return idx unless @uids[idx] end nil end |
#get_display_text(endpoint) ⇒ Object
Returns the DisplayText field of the endpoint with the given name.
282 283 284 |
# File 'lib/xap/schema/xap_bsc_device.rb', line 282 def get_display_text endpoint @endpoints[endpoint.downcase][:DisplayText] end |
#get_level(endpoint) ⇒ Object
Returns the Level field of the endpoint with the given name.
231 232 233 |
# File 'lib/xap/schema/xap_bsc_device.rb', line 231 def get_level endpoint @endpoints[endpoint.downcase][:Level] end |
#get_state(endpoint) ⇒ Object
Returns the State field of the endpoint with the given name.
209 210 211 |
# File 'lib/xap/schema/xap_bsc_device.rb', line 209 def get_state endpoint @endpoints[endpoint.downcase][:State] end |
#get_text(endpoint) ⇒ Object
Returns the Text field of the endpoint with the given name.
261 262 263 |
# File 'lib/xap/schema/xap_bsc_device.rb', line 261 def get_text endpoint @endpoints[endpoint.downcase][:Text] end |
#get_uid(endpoint) ⇒ Object
Returns the UID for the endpoint with the given name, or nil if no such endpoint exists.
204 205 206 |
# File 'lib/xap/schema/xap_bsc_device.rb', line 204 def get_uid endpoint @endpoints[endpoint.downcase][:uid] end |
#handler=(handler) ⇒ Object
Assigns the handler that owns this device, then sends the initial state of all input and output blocks as xAPBSC.info messages.
51 52 53 54 |
# File 'lib/xap/schema/xap_bsc_device.rb', line 51 def handler= handler super handler announce_endpoints end |
#receive_message(msg) ⇒ Object
Called when a message targeting this device’s address is received.
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 |
# File 'lib/xap/schema/xap_bsc_device.rb', line 71 def msg if msg.is_a? XapBscCommand Xap.log "Command message for #{self}" if @output_count > 0 eps = [] if msg.target_addr.wildcard? @outputs.each do |out| eps << out if msg.target_addr.endpoint_match out[:endpoint] end else ep = @endpoints[msg.target_addr.endpoint.downcase] eps << ep if ep end # For each message block, if ID=*, apply the # change to all matched endpoints. If ID!=*, # apply the change to the matching endpoint, # iff that endpoint is in the eps list. msg.each_block do |blk| id = blk.id if id == nil || id == '*' eps.each do |ep| update_endpoint ep, blk end else ep = @uids[id.to_i] if ep && eps.include?(ep) update_endpoint ep, blk end end end end elsif msg.is_a? XapBscQuery Xap.log "Query message for #{self}, target #{msg.target_addr}, wildcard #{msg.target_addr.wildcard?}" if msg.target_addr.wildcard? @endpoints.each do |name, ep| if msg.target_addr.endpoint_match name Xap.log "Matching endpoint found: #{ep[:endpoint]}" send_info ep end end elsif msg.target_addr.endpoint ep = @endpoints[msg.target_addr.endpoint.to_s.downcase] if ep Xap.log "Matching endpoint found: #{ep[:endpoint]}" send_info ep else Xap.log "No matching endpoint found" end else Xap.log "Error: No endpoint was given in the query" end elsif msg.is_a? XapBscInfo Xap.log "Info message for #{self}" elsif msg.is_a? XapBscEvent Xap.log "Event message for #{self}" end end |
#remove_endpoint(ep) ⇒ Object
Removes the given endpoint, which may be the endpoint hash or name. Doesn’t verify that the endpoint actually exists.
180 181 182 183 184 185 186 |
# File 'lib/xap/schema/xap_bsc_device.rb', line 180 def remove_endpoint ep if ep.is_a? String ep = @endpoints[ep.downcase] end @endpoints.delete ep[:endpoint].downcase @uids[ep[:uid]] = nil end |
#set_address(address) ⇒ Object
Sets the xAP address of this virtual device, then sends an xAPBSC.info message for all endpoints.
65 66 67 68 |
# File 'lib/xap/schema/xap_bsc_device.rb', line 65 def set_address address super address announce_endpoints end |
#set_display_text(endpoint, text) ⇒ Object
Sets the DisplayText field of the endpoint with the given name. If the new state is different from the old state, an event message will be generated. Otherwise, an info message will be generated.
289 290 291 292 293 294 295 296 297 298 299 300 |
# File 'lib/xap/schema/xap_bsc_device.rb', line 289 def set_display_text endpoint, text ep = @endpoints[endpoint.downcase] old = ep[:DisplayText] ep[:DisplayText] = old if text != old send_event ep else send_info ep end end |
#set_level(endpoint, level) ⇒ Object
Sets the Level field of the endpoint with the given name. If level is an array, then both the numerator and denominator are replaced. If level is a Fixnum, only the numerator is replaced. If the new level is different from the old level, an event message will be generated. Otherwise, an info message will be generated. Error checking is not performed on the level parameter. Pass nil to remove the level from this endpoint.
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
# File 'lib/xap/schema/xap_bsc_device.rb', line 242 def set_level endpoint, level ep = @endpoints[endpoint.downcase] old = ep[:Level] if level != nil level = [ level, ep[:Level][1] ] if level.is_a? Fixnum ep[:Level] = level else ep.delete :Level end if level != old send_event ep else send_info ep end end |
#set_state(endpoint, state) ⇒ Object
Sets the State field of the endpoint with the given name. If the new state is different from the old state, an event message will be generated. Otherwise, an info message will be generated.
216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/xap/schema/xap_bsc_device.rb', line 216 def set_state endpoint, state raise 'state must be true, false, or nil.' unless state == true || state == false || state == nil ep = @endpoints[endpoint.downcase] old = ep[:State] ep[:State] = state if state != old send_event ep else send_info ep end end |
#set_text(endpoint, text) ⇒ Object
Sets the Text field of the endpoint with the given name. If the new state is different from the old state, an event message will be generated. Otherwise, an info message will be generated.
268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/xap/schema/xap_bsc_device.rb', line 268 def set_text endpoint, text ep = @endpoints[endpoint.downcase] old = ep[:Text] ep[:Text] = old if text != old send_event ep else send_info ep end end |
#uid=(uid) ⇒ Object
Sets the xAP UID of this virtual device, then sends an xAPBSC.info message for all endpoints.
58 59 60 61 |
# File 'lib/xap/schema/xap_bsc_device.rb', line 58 def uid= uid super uid announce_endpoints end |
#uid_endpoint(uid) ⇒ Object
Returns the endpoint having the given UID, if any.
189 190 191 |
# File 'lib/xap/schema/xap_bsc_device.rb', line 189 def uid_endpoint uid @uids[uid] end |