Class: NLHue::Bridge
- Inherits:
-
Object
- Object
- NLHue::Bridge
- Defined in:
- lib/nlhue/bridge.rb
Overview
A class representing a Hue bridge. A Bridge object may not refer to an actual Hue bridge if verify() hasn’t succeeded. Manages a list of lights and groups on the bridge. HTTP requests to the bridge are queued and sent one at a time to prevent overloading the bridge’s CPU.
Constant Summary collapse
- RATE_LIMIT =
Seconds to wait after an update round finishes before sending more updates to lights and groups.
0.2
- @@bridge_cbs =
callbacks notified when a bridge has its first successful update
[]
Instance Attribute Summary collapse
-
#addr ⇒ Object
Returns the value of attribute addr.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#serial ⇒ Object
readonly
Returns the value of attribute serial.
-
#username ⇒ Object
Returns the value of attribute username.
-
#whitelist ⇒ Object
readonly
Returns the value of attribute whitelist.
Class Method Summary collapse
-
.add_bridge_callback(&block) ⇒ Object
Adds a callback to be called with a Bridge object and a status each time a Bridge has its first successful update, adds or removes lights or groups, or becomes unregistered.
-
.notify_bridge_callbacks(br, status) ⇒ Object
Sends the given bridge to all attached first update callbacks.
-
.remove_bridge_callback(cb) ⇒ Object
Removes the given callback (returned by add_bridge_callback) from Bridge first update/unregistration notifications.
Instance Method Summary collapse
-
#add_target(t, &block) ⇒ Object
Schedules a Light, Scene, or Group to have its deferred values sent the next time the rate limiting timer fires, or immediately if the rate limiting timer has expired.
-
#add_update_callback(&cb) ⇒ Object
Adds a callback to be notified when a subscription update is received, or when a subscription update fails.
-
#check_json(response) ⇒ Object
Checks for a valid JSON-containing response from an HTTP request method, returns an error if invalid or no response.
-
#check_username(username) ⇒ Object
Throws errors if the given username is invalid (may not catch all invalid names).
-
#clean ⇒ Object
Unsubscribes from bridge updates, marks this bridge as unregistered, notifies global bridge callbacks added with add_bridge_callback, then removes references to configuration, lights, groups, and update callbacks.
-
#create_group(name, lights, &block) ⇒ Object
Creates a new group with the given name and list of lights.
-
#delete_api(subpath, category = nil, &block) ⇒ Object
Makes a DELETE request under the API using this Bridge’s stored username.
-
#delete_group(group, &block) ⇒ Object
Deletes the given NLHue::Group on this bridge.
-
#find_scene(prefix) ⇒ Object
Returns the scene with an exactly matching ID, the most recently created Scene with a name starting with
prefix
(that is, the scene occurring last in an alphanumeric sort), or nil if no match was found. -
#get_api(subpath, category = nil, &block) ⇒ Object
Makes a GET request under the API using this Bridge’s stored username.
-
#groups ⇒ Object
Returns a Hash mapping group IDs to Group objects representing the groups known to this bridge, including the default group 0 that contains all lights from this bridge.
-
#initialize(addr, serial = nil) ⇒ Bridge
constructor
addr - The IP address or hostname of the Hue bridge.
-
#lights ⇒ Object
Returns a Hash mapping light IDs to Light objects, representing the lights known to the Hue bridge.
-
#num_groups ⇒ Object
The number of groups known to this bridge, including the default group that contains all lights known to the bridge.
-
#num_lights ⇒ Object
The number of lights known to this bridge.
-
#num_scenes ⇒ Object
The number of scenes found on the bridge.
-
#post_api(subpath, data, category = nil, content_type = nil, &block) ⇒ Object
Makes a POST request under the API using this Bridge’s stored username.
-
#put_api(subpath, data, category = nil, content_type = nil, &block) ⇒ Object
Makes a PUT request under the API using this Bridge’s stored username.
-
#register(devicetype, &block) ⇒ Object
Attempts to register with the Bridge.
-
#registered? ⇒ Boolean
Returns whether the Bridge object believes it is registered with its associated Hue bridge.
-
#remove_update_callback(cb) ⇒ Object
Removes the given callback (returned by add_update_callback) from the list of callbacks notified with subscription events.
-
#scan_active? ⇒ Boolean
Returns true if a scan for lights is active (as of the last call to #update), false otherwise.
-
#scan_lights(&block) ⇒ Object
Initiates a scan for new lights.
-
#scan_status(request = false, &block) ⇒ Object
Calls the given block (if given) with true and the last known light scan status from the bridge.
-
#scenes ⇒ Object
Returns a Hash mapping scene IDs to Scene objects.
-
#subscribe(interval = 1) ⇒ Object
Starts a timer that retrieves the current state of the bridge every interval seconds.
-
#subscribed? ⇒ Boolean
Returns true if this bridge is subscribed (i.e. periodically polling the Hue bridge for updates).
-
#to_h(include_config = false) ⇒ Object
Returns a Hash with information about this bridge: { :addr => “[IP address]”, :name => “[name]”, :serial => “[serial number]”, :registered => true/false, :scan => [return value of #scan_status], :lights => [hash containing Light objects (see #lights)], :groups => [hash containing Group objects (see #groups)], :scenes => [hash containing Scene objects (see #scenes)], :config => [raw config from bridge] if include_config }.
-
#to_json(*args) ⇒ Object
Return value of to_h converted to a JSON string.
-
#to_s ⇒ Object
“Hue Bridge: [IP]: [Friendly Name] ([serial]) - N lights”.
-
#unregister(username = nil, &block) ⇒ Object
Deletes the given
username
(or this Bridge object’s current username ifusername
is nil) from the Bridge’s whitelist, sets this Bridge’s username to nil, and sets its registered state to false. -
#unsubscribe ⇒ Object
Stops the timer started by subscribe(), if one is running.
-
#update(&block) ⇒ Object
Updates the Bridge object with the lights, groups, and config of the Hue bridge.
-
#updated? ⇒ Boolean
Returns whether the Bridge object has had at least one successful update from #update.
-
#verified? ⇒ Boolean
Indicates whether verification succeeded.
-
#verify(&block) ⇒ Object
Calls the given block with true or false if verification by description.xml succeeds or fails.
Constructor Details
#initialize(addr, serial = nil) ⇒ Bridge
addr - The IP address or hostname of the Hue bridge. serial - The serial number of the bridge, if available (parsed from the USN header in a UPnP response)
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 |
# File 'lib/nlhue/bridge.rb', line 85 def initialize addr, serial = nil @addr = addr @verified = false @username = nil @name = nil @config = nil @registered = false @lights = {} @groups = {} @scenes = {} @whitelist = {} @lightscan = {'lastscan' => 'none'} if serial && serial =~ /^[0-9A-Fa-f]{12}$/ @serial = serial.downcase else @serial = nil end @request_queue = NLHue::RequestQueue.new addr, 2 @update_timer = nil @update_callbacks = [] @rate_timer = nil @rate_targets = {} @rate_proc = proc do if @rate_targets.empty? log "No targets, canceling rate timer." # XXX @rate_timer.cancel if @rate_timer @rate_timer = nil else log "Sending targets from rate timer." # XXX send_targets do @rate_timer = EM::Timer.new(RATE_LIMIT, @rate_proc) end end end end |
Instance Attribute Details
#addr ⇒ Object
Returns the value of attribute addr.
40 41 42 |
# File 'lib/nlhue/bridge.rb', line 40 def addr @addr end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
40 41 42 |
# File 'lib/nlhue/bridge.rb', line 40 def name @name end |
#serial ⇒ Object (readonly)
Returns the value of attribute serial.
40 41 42 |
# File 'lib/nlhue/bridge.rb', line 40 def serial @serial end |
#username ⇒ Object
Returns the value of attribute username.
40 41 42 |
# File 'lib/nlhue/bridge.rb', line 40 def username @username end |
#whitelist ⇒ Object (readonly)
Returns the value of attribute whitelist.
40 41 42 |
# File 'lib/nlhue/bridge.rb', line 40 def whitelist @whitelist end |
Class Method Details
.add_bridge_callback(&block) ⇒ Object
Adds a callback to be called with a Bridge object and a status each time a Bridge has its first successful update, adds or removes lights or groups, or becomes unregistered. Bridge callbacks will be called after any corresponding :add or :del disco event is delivered. Returns a Proc object that may be passed to remove_update_cb.
Callback parameters: Bridge first update: [Bridge], true
Bridge added/removed lights or groups: [Bridge], true
Bridge unregistered: [Bridge], false
60 61 62 63 |
# File 'lib/nlhue/bridge.rb', line 60 def self.add_bridge_callback &block @@bridge_cbs << block block end |
.notify_bridge_callbacks(br, status) ⇒ Object
Sends the given bridge to all attached first update callbacks.
72 73 74 75 76 77 78 79 80 |
# File 'lib/nlhue/bridge.rb', line 72 def self.notify_bridge_callbacks br, status @@bridge_cbs.each do |cb| begin cb.call br, status rescue => e log_e e, "Error calling a first update callback" end end end |
.remove_bridge_callback(cb) ⇒ Object
Removes the given callback (returned by add_bridge_callback) from Bridge first update/unregistration notifications.
67 68 69 |
# File 'lib/nlhue/bridge.rb', line 67 def self.remove_bridge_callback cb @@bridge_cbs.delete cb end |
Instance Method Details
#add_target(t, &block) ⇒ Object
Schedules a Light, Scene, or Group to have its deferred values sent the next time the rate limiting timer fires, or immediately if the rate limiting timer has expired. Starts the rate limiting timer if it is not running.
745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 |
# File 'lib/nlhue/bridge.rb', line 745 def add_target t, &block raise 'Target must respond to :send_changes' unless t.respond_to?(:send_changes) raise "Target is from #{t.bridge.serial} not this bridge (#{@serial})" unless t.bridge == self log "Adding deferred target #{t}" # XXX @rate_targets[t] ||= [] @rate_targets[t] << block if block_given? # TODO: Use different timers for different request types unless @rate_timer log "No rate timer -- sending targets on next tick" # XXX # Waiting until the next tick allows multiple # updates to be queued in the current tick that # will all go out at the same time. EM.next_tick do log "It's next tick -- sending targets now" # XXX send_targets end log "Setting rate timer" @rate_timer = EM::Timer.new(RATE_LIMIT, @rate_proc) else log "Rate timer is set -- not sending targets now" # XXX end end |
#add_update_callback(&cb) ⇒ Object
Adds a callback to be notified when a subscription update is received, or when a subscription update fails. The return value may be passed to remove_update_callback.
Callback parameters: Update successful: true, [lights or groups changed: true/false]
Update failed: false, [exception]
253 254 255 256 |
# File 'lib/nlhue/bridge.rb', line 253 def add_update_callback &cb @update_callbacks << cb cb end |
#check_json(response) ⇒ Object
Checks for a valid JSON-containing response from an HTTP request method, returns an error if invalid or no response. Does not consider non-200 HTTP response codes as errors. Returns true and the received JSON if no error occurred, or false and an exception if an error did occur. Marks this bridge as not registered if there is a NotRegisteredError.
632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 |
# File 'lib/nlhue/bridge.rb', line 632 def check_json response status = false result = nil begin raise 'No response received.' if response == false if response.is_a?(Hash) status = true result_msgs = [] result = JSON.parse response[:content] if result.is_a? Array result.each do |v| if v.is_a?(Hash) && v['error'].is_a?(Hash); then status = false result_msgs << v['error']['description'] end end end unless status if result_msgs.include?('link button not pressed') raise LinkButtonError.new elsif result_msgs.include?('unauthorized user') was_reg = @registered @registered = false Bridge.notify_bridge_callbacks self, false if was_reg raise NotRegisteredError.new else raise StandardError.new(result_msgs.join(', ')) end end end rescue => e status = false result = e end return status, result end |
#check_username(username) ⇒ Object
Throws errors if the given username is invalid (may not catch all invalid names).
620 621 622 623 624 |
# File 'lib/nlhue/bridge.rb', line 620 def check_username username raise 'Username must be a String' unless username.is_a?(String) raise 'Username must be >= 10 characters.' unless username.to_s.length >= 10 raise 'Spaces are not permitted in usernames.' if username =~ /[[:space:]]/ end |
#clean ⇒ Object
Unsubscribes from bridge updates, marks this bridge as unregistered, notifies global bridge callbacks added with add_bridge_callback, then removes references to configuration, lights, groups, and update callbacks.
604 605 606 607 608 609 610 611 612 613 614 615 616 |
# File 'lib/nlhue/bridge.rb', line 604 def clean was_updated = updated? unsubscribe @registered = false Bridge.notify_bridge_callbacks self, false if was_updated @verified = false @config = nil @lights.clear @groups.clear @update_callbacks.clear end |
#create_group(name, lights, &block) ⇒ Object
Creates a new group with the given name and list of lights. The given block will be called with true and a NLHue::Group object on success, false and an error on failure. If group creation succeeds, all bridge callbacks added with Bridge.add_bridge_callback will be notified after the new group is yielded to the block (if a block is given). Note that the group’s name may be changed by the bridge.
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 |
# File 'lib/nlhue/bridge.rb', line 515 def create_group name, lights, &block raise "No group name was given" unless name.is_a?(String) && name.length > 0 raise "No lights were given" unless lights.is_a?(Array) && lights.length > 0 light_ids = [] lights.each do |l| raise "All given lights must be NLHue::Light objects" unless l.is_a?(Light) raise "Light #{l.id} (#{l.name}) is not from this bridge." if l.bridge != self light_ids << l.id.to_s end group_data = { :lights => light_ids, :name => name }.to_json post_api '/groups', group_data, :lights do |response| status, result = check_json response begin result = result.first if result.is_a? Array if status && result['success'] id = result['success']['id'].split('/').last.to_i raise "Invalid ID received for new group: '#{result['success']['id']}'" unless id > 0 group = Group.new(self, id, { 'name' => name, 'lights' => light_ids, 'action' => {} }) group.update do |upstatus, upresult| if upstatus @groups[id] = group Bridge.notify_bridge_callbacks self, true yield true, group if block_given? else yield upstatus, upresult if block_given? end end else raise result end rescue => e yield false, e if block_given? end end end |
#delete_api(subpath, category = nil, &block) ⇒ Object
Makes a DELETE request under the API using this Bridge’s stored username.
737 738 739 |
# File 'lib/nlhue/bridge.rb', line 737 def delete_api subpath, category=nil, &block @request_queue.delete "/api/#{api_key}#{subpath}", category, &block end |
#delete_group(group, &block) ⇒ Object
Deletes the given NLHue::Group on this bridge. Raises an exception if the group is group 0. Calls the given block with true and a message on success, or false and an error on failure. Bridge notification callbacks will be called after the result is yielded.
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 |
# File 'lib/nlhue/bridge.rb', line 562 def delete_group group, &block raise "No group was given to delete" if group.nil? raise "Group must be a NLHue::Group object" unless group.is_a?(Group) raise "Group is not from this bridge" unless group.bridge == self raise "Cannot delete group 0" if group.id == 0 delete_api "/groups/#{group.id}", :lights do |response| status, result = check_json response if status @groups.delete group.id end yield status, result if block_given? if status Bridge.notify_bridge_callbacks self, true end end end |
#find_scene(prefix) ⇒ Object
Returns the scene with an exactly matching ID, the most recently created Scene with a name starting with prefix
(that is, the scene occurring last in an alphanumeric sort), or nil if no match was found.
497 498 499 500 501 502 503 504 505 506 |
# File 'lib/nlhue/bridge.rb', line 497 def find_scene(prefix) return @scenes[prefix] if @scenes.include? prefix prefix = prefix.downcase @scenes.select{|id, scene| scene.name.downcase.start_with?(prefix) }.values.max_by{|s| s.name } end |
#get_api(subpath, category = nil, &block) ⇒ Object
Makes a GET request under the API using this Bridge’s stored username.
719 720 721 |
# File 'lib/nlhue/bridge.rb', line 719 def get_api subpath, category=nil, &block @request_queue.get "/api/#{api_key}#{subpath}", &block end |
#groups ⇒ Object
Returns a Hash mapping group IDs to Group objects representing the groups known to this bridge, including the default group 0 that contains all lights from this bridge.
472 473 474 |
# File 'lib/nlhue/bridge.rb', line 472 def groups @groups.clone end |
#lights ⇒ Object
Returns a Hash mapping light IDs to Light objects, representing the lights known to the Hue bridge.
460 461 462 |
# File 'lib/nlhue/bridge.rb', line 460 def lights @lights.clone end |
#num_groups ⇒ Object
The number of groups known to this bridge, including the default group that contains all lights known to the bridge.
478 479 480 |
# File 'lib/nlhue/bridge.rb', line 478 def num_groups @groups.length end |
#num_lights ⇒ Object
The number of lights known to this bridge.
465 466 467 |
# File 'lib/nlhue/bridge.rb', line 465 def num_lights @lights.length end |
#num_scenes ⇒ Object
The number of scenes found on the bridge.
489 490 491 |
# File 'lib/nlhue/bridge.rb', line 489 def num_scenes @scenes.length end |
#post_api(subpath, data, category = nil, content_type = nil, &block) ⇒ Object
Makes a POST request under the API using this Bridge’s stored username.
725 726 727 |
# File 'lib/nlhue/bridge.rb', line 725 def post_api subpath, data, category=nil, content_type=nil, &block @request_queue.post "/api/#{api_key}#{subpath}", data, category, content_type, &block end |
#put_api(subpath, data, category = nil, content_type = nil, &block) ⇒ Object
Makes a PUT request under the API using this Bridge’s stored username.
731 732 733 |
# File 'lib/nlhue/bridge.rb', line 731 def put_api subpath, data, category=nil, content_type=nil, &block @request_queue.put "/api/#{api_key}#{subpath}", data, category, content_type, &block end |
#register(devicetype, &block) ⇒ Object
Attempts to register with the Bridge. The block will be called with true and the result array if registration succeeds, false and an Exception if not. If registration succeeds, the Bridge object’s current username will be set to the username returned by the bridge. If the Bridge is already registered it will not be re-registered, and the block will be called with true and the current username. Call #update after registration succeeds. #registered? will not return true until #update has succeeded.
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/nlhue/bridge.rb', line 180 def register devicetype, &block raise NotVerifiedError.new unless @verified if @username && @registered yield true, @username return end msg = %Q{{"devicetype":#{devicetype.to_json}}} @request_queue.post '/api', msg, :registration, nil, 6 do |response| status, result = check_json response if status @username = result.first['success']['username'] end yield status, result end end |
#registered? ⇒ Boolean
Returns whether the Bridge object believes it is registered with its associated Hue bridge. Set to true when #update or #register succeeds, false if a NotRegisteredError occurs.
454 455 456 |
# File 'lib/nlhue/bridge.rb', line 454 def registered? @registered end |
#remove_update_callback(cb) ⇒ Object
Removes the given callback (returned by add_update_callback) from the list of callbacks notified with subscription events.
260 261 262 |
# File 'lib/nlhue/bridge.rb', line 260 def remove_update_callback cb @update_callbacks.delete cb end |
#scan_active? ⇒ Boolean
Returns true if a scan for lights is active (as of the last call to #update), false otherwise.
427 428 429 |
# File 'lib/nlhue/bridge.rb', line 427 def scan_active? @lightscan['lastscan'] == 'active' end |
#scan_lights(&block) ⇒ Object
Initiates a scan for new lights. If a block is given, yields true if the scan was started, an exception if there was an error.
374 375 376 377 378 379 380 381 382 383 384 |
# File 'lib/nlhue/bridge.rb', line 374 def scan_lights &block post_api '/lights', nil do |response| begin status, result = check_json response @lightscan['lastscan'] = 'active' if status yield status if block_given? rescue => e yield e end end end |
#scan_status(request = false, &block) ⇒ Object
Calls the given block (if given) with true and the last known light scan status from the bridge. Requests the current scan status from the bridge if request is true. The block will be called with false and an exception if an error occurs during a request. Returns the last known scan status.
The scan status is a Hash with the following form: { ‘1’ => { ‘name’ => ‘New Light 1’ }, # If new lights were found ‘2’ => { ‘name’ => ‘New Light 2’ }, ‘lastscan’ => ‘active’/‘none’/ISO8601:2004 }
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 |
# File 'lib/nlhue/bridge.rb', line 398 def scan_status request=false, &block if request get_api '/lights/new' do |response| begin status, result = check_json response if status # Update group 0 if new lights are found or when a scan completes if @lightscan['lastscan'] == 'active' && result['lastscan'] != 'active' puts "Updating group 0" # XXX @groups[0].update end @lightscan = result end yield status, result if block_given? rescue => e yield e end end else yield true, @lightscan if block_given? end @lightscan unless block_given? end |
#scenes ⇒ Object
Returns a Hash mapping scene IDs to Scene objects. Unlike lights and groups, scenes have String IDs.
484 485 486 |
# File 'lib/nlhue/bridge.rb', line 484 def scenes @scenes.clone end |
#subscribe(interval = 1) ⇒ Object
Starts a timer that retrieves the current state of the bridge every interval seconds. Does nothing if this Bridge is already subscribed.
225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/nlhue/bridge.rb', line 225 def subscribe interval=1 return if @update_timer update_proc = proc { update do |status, result| @update_timer = EM::Timer.new(interval, update_proc) if @update_timer end } @update_timer = EM::Timer.new(interval, update_proc) end |
#subscribed? ⇒ Boolean
Returns true if this bridge is subscribed (i.e. periodically polling the Hue bridge for updates).
447 448 449 |
# File 'lib/nlhue/bridge.rb', line 447 def subscribed? !!@update_timer end |
#to_h(include_config = false) ⇒ Object
Returns a Hash with information about this bridge: { :addr => “[IP address]”, :name => “[name]”, :serial => “[serial number]”, :registered => true/false, :scan => [return value of #scan_status], :lights => [hash containing Light objects (see #lights)], :groups => [hash containing Group objects (see #groups)], :scenes => [hash containing Scene objects (see #scenes)], :config => [raw config from bridge] if include_config }
Do not modify the included lights and groups hashes.
696 697 698 699 700 701 702 703 704 705 706 707 708 709 |
# File 'lib/nlhue/bridge.rb', line 696 def to_h include_config=false h = { :addr => @addr, :name => @name, :serial => @serial, :registered => @registered, :scan => @lightscan, :lights => @lights, :groups => @groups, :scenes => @scenes, } h[:config] = @config if include_config h end |
#to_json(*args) ⇒ Object
Return value of to_h converted to a JSON string. Options: :include_config => true – include raw config returned by the bridge
713 714 715 |
# File 'lib/nlhue/bridge.rb', line 713 def to_json *args to_h(args[0].is_a?(Hash) && args[0][:include_config]).to_json(*args) end |
#to_s ⇒ Object
“Hue Bridge: [IP]: [Friendly Name] ([serial]) - N lights”
676 677 678 679 680 |
# File 'lib/nlhue/bridge.rb', line 676 def to_s str = "Hue Bridge: #{@addr}: #{@name} (#{@serial}) - #{@lights.length} lights" str << " (#{registered? ? '' : 'un'}registered)" str end |
#unregister(username = nil, &block) ⇒ Object
Deletes the given username
(or this Bridge object’s current username if username
is nil) from the Bridge’s whitelist, sets this Bridge’s username to nil, and sets its registered state to false.
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/nlhue/bridge.rb', line 204 def unregister username = nil, &block raise NotVerifiedError.new unless @verified username ||= @username @request_queue.delete "/api/#{username}/config/whitelist/#{username}", :registration, 6 do |response| status, result = check_json response if @username == username && status @registered = false @username = nil Bridge.notify_bridge_callbacks self, false end yield status, result end end |
#unsubscribe ⇒ Object
Stops the timer started by subscribe(), if one is running.
238 239 240 241 |
# File 'lib/nlhue/bridge.rb', line 238 def unsubscribe @update_timer.cancel if @update_timer @update_timer = nil end |
#update(&block) ⇒ Object
Updates the Bridge object with the lights, groups, and config of the Hue bridge. Also updates the current light scan status on the first update or if the Bridge thinks a scan is currently active. On success the given block will be called with true and whether the lights/groups were changed, false and an exception on error.
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 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 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 |
# File 'lib/nlhue/bridge.rb', line 270 def update &block @request_queue.get "/api/#{api_key}", :info do |response| status, result = check_json response changed = false begin if status first_update = !@registered # TODO: Extract a helper method for adding new # members to and removing old members from a list @config = result @config['lights'].each do |id, info| id = id.to_i if @lights[id].is_a? Light @lights[id].handle_json info else @lights[id] = Light.new(self, id, info) changed = true end end @lights.select! do |id, light| incl = @config['lights'].include? id.to_s changed ||= !incl incl end set_name @config['config']['name'] unless @name @serial ||= @config['config']['mac'].gsub(':', '').downcase @registered = true unless @groups[0].is_a? Group @groups[0] = Group.new(self, 0) get_api '/groups/0', :info do |response| status, result = check_json response if status && @groups[0] @groups[0].handle_json result end end end @config['groups'].each do |id, info| if @groups[id.to_i].is_a? Group @groups[id.to_i].handle_json info else @groups[id.to_i] = Group.new(self, id.to_i, info) changed = true end end @groups.select! do |id, light| incl = @config['groups'].include?(id.to_s) || id == 0 changed ||= !incl incl end @config['scenes'].each do |id, info| if @scenes[id].is_a? Scene @scenes[id].handle_json info else @scenes[id] = Scene.new(self, id, info) changed = true end end @scenes.select! do |id, scene| incl = @config['scenes'].include?(id.to_s) changed ||= !incl incl end wl = @config['config']['whitelist'] if wl != @whitelist @whitelist = wl changed = true end if changed @scenes = Hash[@scenes.sort_by{|id, s| s.name}] end # TODO: schedules, rules, sensors, etc. scan_status true if first_update || @lightscan['lastscan'] == 'active' Bridge.notify_bridge_callbacks self, true if first_update || changed end rescue => e log_e e, "Bridge #{@serial} update raised an exception" status = false result = e end result = changed if status notify_update_callbacks status, result yield status, result end end |
#updated? ⇒ Boolean
Returns whether the Bridge object has had at least one successful update from #update.
433 434 435 |
# File 'lib/nlhue/bridge.rb', line 433 def updated? @config.is_a? Hash end |
#verified? ⇒ Boolean
Indicates whether verification succeeded. A Hue bridge has been verified to exist at the address given to the constructor or to #addr= if this returns true. Use #verify to perform verification if this returns false.
441 442 443 |
# File 'lib/nlhue/bridge.rb', line 441 def verified? @verified end |
#verify(&block) ⇒ Object
Calls the given block with true or false if verification by description.xml succeeds or fails. If verification has already been performed, the block will be called immediately with true.
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 |
# File 'lib/nlhue/bridge.rb', line 128 def verify &block if @verified yield true return true end @request_queue.get '/description.xml', :info, 4 do |result| puts "Description result: #{result.inspect}" # XXX if result.is_a?(Hash) && result[:status] == 200 @desc = REXML::Document.new result[:content] @desc.write($stdout, 4, true) # XXX @desc.elements.each('friendlyName') do |el| puts "Friendly name: #{@name}" # XXX set_name el.text end @desc.elements.each('serialNumber') do |el| puts "Serial number: #{@serial}" # XXX @serial = el.text.downcase end @desc.elements.each('modelName') do |el| puts "modelName: #{el.text}" # XXX if el.text.include? 'Philips hue' @verified = true end end # FIXME: Delete this line when converted to em-http-request; this # works around the empty :content returned by EM::HttpClient # # See commits: # 34110773fc45bfdd56c32972650f9d947d8fac78 # 6d8d7a0566e3c51c3ab15eb2358dde3e518594d3 @verified = true end begin yield @verified rescue => e log_e e, "Error notifying block after verification" end end end |