Skip to content

Commit

Permalink
Improve handling of the bridge connection from bulb. Added transition…
Browse files Browse the repository at this point in the history
…time option. Added schedule status and deleting.
  • Loading branch information
AaronH committed Nov 10, 2012
1 parent 5726374 commit 75d1aa2
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 42 deletions.
28 changes: 14 additions & 14 deletions README.md
@@ -1,13 +1,13 @@
RubyHue
================

This is a very early attempt to create a Ruby library for controlling the [Philips Hue](http://www.meethue.com) lighting system. The API has not yet been released, but there are [several](http://www.nerdblog.com/2012/10/a-day-with-philips-hue.html) [people](http://rsmck.co.uk/hue) working to figure it out.
This is a very early attempt to create a Ruby library for controlling the [Philips Hue](http://www.meethue.com) lighting system. The API has not yet been released, but there are [several](http://www.nerdblog.com/2012/10/a-day-with-philips-hue.html) [people](http://rsmck.co.uk/hue) working to figure it out.

# WARNING
All of this is very experimental and could permanently damage your awesome (but ridiculously expensive) lightbulbs. As such, exercise extreme caution.

## Getting Started
You can get a [great overview](http://rsmck.co.uk/hue) of the options and limitations of the lights from Ross McKillop.
You can get a [great overview](http://rsmck.co.uk/hue) of the options and limitations of the lights from Ross McKillop.

You will need to find the IP address of your bridge unit and also generate a unique ID (UUID works great) for your controlling application and add them to the top of the `hue.rb` file.

Expand All @@ -25,28 +25,28 @@ You can see all of the lights attached to your controller by querying the bridge

```ruby
>> Hue::Bridge.identities
=> {"1"=>"Master Bedroom Dresser", "2"=>"Wife Bedside", "3"=>"Bedside (front)", "4"=>"Bedside (back)", "5"=>"Family Room Desk", "6"=>"Family Room", "7"=>"Living Room Square"}
=> {"1"=>"Master Bedroom Dresser", "2"=>"Wife Bedside", "3"=>"Bedside (front)", "4"=>"Bedside (back)", "5"=>"Family Room Desk", "6"=>"Family Room", "7"=>"Living Room Square"}
```

If you know the ID number of a particular lamp, you can access it directly.

```ruby
>> b = Hue::Bulb.new(5)
=> #<Hue::Bulb:0x007fe35a3586b8 @id=5, @hub=#<Hue::Bridge:0x007fe35a358690 @light_id="5">>
=> #<Hue::Bulb:0x007fe35a3586b8 @id=5, @hub=#<Hue::Bridge:0x007fe35a358690 @light_id="5">>

# on/off
>> b.on?
=> false
=> false

>> b.on
=> true
=> true

>> b.on?
=> true
=> true

# settings
>> b.settings
=> {"ct"=>343, "on"=>true, "bri"=>240}
=> {"ct"=>343, "on"=>true, "bri"=>240}

>> b.brightness = 128
=> 128
Expand All @@ -55,23 +55,23 @@ If you know the ID number of a particular lamp, you can access it directly.
=> true

>> b.settings
=> {"hue"=>45000, "sat"=>180, "on"=>true, "bri"=>128}
=> {"hue"=>45000, "sat"=>180, "on"=>true, "bri"=>128}

# blinking
>> b.blinking?
=> false
=> false

>> b.blink
=> nil
=> nil

>> b.blinking?
=> true
=> true

>> b.blink false
=> nil
=> nil

>> b.blinking?
=> false
=> false
```

## Experimental
Expand Down
54 changes: 43 additions & 11 deletions bridge.rb
Expand Up @@ -3,35 +3,62 @@ module Hue
class Bridge
attr_accessor :light_id

def initialize(light_num)
def self.shared
@shared ||= Bridge.new
end

def self.method_missing(method, *args, &block)
if args.empty?
self.shared.send method
else
self.shared.send method, *args
end
end

def initialize(light_num = nil)
self.light_id = light_num.to_s
end

def self.uri(*args)
def uri(*args)
URI [BASE, UUID, args].flatten.reject{|x| x.to_s.strip == ''}.join('/')
end

def self.status
JSON.parse Net::HTTP.get(Bridge.uri)
def status
JSON.parse Net::HTTP.get(Bridge.shared.uri)
end

def self.lights
def lights
status['lights']
end

def self.identities
def identities
Hash[lights.map{|k, v| [k, v['name']] }]
end

def self.bulbs
def bulbs
@bulbs ||= lights.keys.map{|b| Bulb.new b}
end

def self.reload
def reload
@bulbs = nil
self
end

def schedules
status['schedules']
end

def remove_schedule(schedule_id)
delete uri('schedules', schedule_id)
puts "Removed schedule #{schedule_id}"
end

def remove_all_schedules
ids = schedules.keys.map(&:to_i).sort.reverse
puts "Removing #{ids.size} schedule#{'s' if ids.size != 1}..."
ids.each{|x| remove_schedule x}
end

def display(response = nil)
if response and response.code.to_s != '200'
puts "Response #{response.code} #{response.message}: #{JSON.parse(response.body).first}"
Expand All @@ -42,11 +69,11 @@ def display(response = nil)
end

def update_state(settings)
update Bridge.uri('lights', light_id, 'state'), settings
update uri('lights', light_id, 'state'), settings if light_id
end

def update_base(settings)
update Bridge.uri('lights', light_id), settings
update uri('lights', light_id), settings if light_id
end

def update(url, settings = {})
Expand All @@ -55,6 +82,11 @@ def update(url, settings = {})
display Net::HTTP.new(url.host, url.port).start {|http| http.request(request) }
end

def delete(url)
request = Net::HTTP::Delete.new(url.request_uri, initheader = {'Content-Type' =>'application/json'})
display Net::HTTP.new(url.host, url.port).start{|http| http.request(request)}
end

end

end # Hue
end # Hue
47 changes: 30 additions & 17 deletions bulb.rb
Expand Up @@ -2,11 +2,11 @@ module Hue

class Bulb

attr_accessor :id, :hub, :stash
attr_accessor :id, :stash, :options

def initialize(light_num)
self.id = light_num
self.hub = Bridge.new light_num
def initialize(light_num, options = {})
self.id = light_num
self.options = options
end

def status
Expand All @@ -22,15 +22,16 @@ def [](item)
end

def update(settings = {})
hub.update_state settings
puts @options.merge(settings).inspect
Bridge.update Bridge.uri('lights', id, 'state'), @options.merge(settings)
end

def name
status['name']
end

def name=(_name)
hub.update_base name: _name
Bridge.update uri('lights', light_id), name: _name
end

def on?
Expand Down Expand Up @@ -65,6 +66,7 @@ def hue
end

def hue=(_hue)
_hue = (_hue * (65536.0 / 360)).to_i
update hue: _hue
hue
end
Expand All @@ -78,6 +80,16 @@ def sat=(_sat)
sat
end

def transition_time
# transition time in seconds
(options[:transitiontime] || 1).to_f / 10
end

def transition_time=(time)
# transition time in seconds
self.options[:transitiontime] = (time * 10).to_i
end

def colortemp
self[:ct]
end
Expand Down Expand Up @@ -110,15 +122,16 @@ def flash

def settings
state = states
case state['colormode']
when 'ct'
{'ct' => state['ct']}
when 'xy'
{'xy' => state['xy']}
when 'hs'
{'hue' => state['hue'], 'sat' => state['sat']}
end.merge('on' => state['on'], 'bri' => state['bri'])
options.merge case state['colormode']
when 'ct'
{'ct' => state['ct']}
when 'xy'
{'xy' => state['xy']}
when 'hs'
{'hue' => state['hue'], 'sat' => state['sat']}
end.merge('on' => state['on'], 'bri' => state['bri'])
end
alias :color :settings

def stash!
self.stash ||= settings
Expand All @@ -144,10 +157,10 @@ def candle(repeat = 15)
hue = ((rand * 5460) + 5460).to_i
sat = rand(64) + 170
bri = rand(32) + 16
update hue: hue, sat: sat, bri: bri

# delay = (rand * 0.5) + (@delay ||= 0)
# sleep delay
delay = (rand * 0.5) + (@delay ||= 0)
update(hue: hue, sat: sat, bri: bri, transitiontime: (delay * 10).to_i)
sleep delay
end
restore!
end
Expand Down

0 comments on commit 75d1aa2

Please sign in to comment.