Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Improve initial user setup process, update README to match

User will now pass IP and username as config options
The plugin will make sure that the user is registered before submitting commands

Also pulled the HueEntity class into a seperate file
  • Loading branch information...
commit 11dea17f69ec8e420258d54e89e62666c61f290a 1 parent 9b9ca86
Brandon Evans authored
29 README.md
View
@@ -13,19 +13,24 @@ This is a SiriProxy plugin to control Philips Hue lights with Siri. It has been
## Setup ##
-- Pick a username that you'll use to connect to your Hue device, and make a MD5 hash of it. You can either [google it](https://www.google.com/?q=md5+generator) or type `md5 -s *your username*` in a terminal. Save this hash for the next steps.
-- Install [resty](https://github.com/micha/resty) or a similar tool to make HTTP requests. I'll let you go check out the instructions on that page, but it amounts to downloading resty with `curl` and then sourcing it with `source resty` so that you can use it.
-- Press the link button on your Hue bridge.
-- Make a POST HTTP request to http://*YourHueHubIP*/api with the data:
- `{"username": "YourMD5Hash", "devicetype": "SiriProxyHue"}`. Using resty I first set the base URL to this address with `resty http://10.0.1.16/api` and `POST '{"username": "YourMD5Hash", "devicetype": "SiriProxyHue"}'` to send the request. You should get a response like `{"success":{"username":"YourMD5HashFromBefore"}}`
-- Store this MD5 hash in the hueKey class variable in lib/siriproxy-hue.rb.
-- Store the Hue's local IP address (that you used with resty) in the hueIP class variable in the same file.
-- Follow the plugin install instructions from [SiriProxy](https://github.com/jimmykane/The-Three-Little-Pigs-Siri-Proxy/wiki/Plugin%20Developer%20Guide). I had some trouble until I made sure that libmysql-dev was also installed before I could `rake install` SiriProxy, so use your preferred package manager to do that if necessary. Notably, add the following to your config.yml file:
-
-- plugins:
-
+- Follow the setup instructions for [SiriProxy](https://github.com/jimmykane/The-Three-Little-Pigs-Siri-Proxy#set-up-instructions) if you haven't already, then copy SiriProxy-Hue into the plugins folder.
+- Find out the IP address of your Hue bridge
+- Add the plugin in the SiriProxy config.yml file, substituting your own information:
+
+- plugins:
+
- name: 'Hue'
path: "./plugins/siriproxy-hue"
+ bridge_ip: "10.0.1.2"
+ username: "JohnnyAppleseed"
+
+- Run `siriproxy update`
+- Run `rvmsudo bundle exec ./siriproxy-restarter`
+- Say one of the commands above. The first time Siri will prompt you to press the link button on your Hue bridge.
+
+## Support ##
+
+I'm more than happy to look into issues with SiriProxy-Hue itself, but please respect that I won't be able to provide installation support for you.
## Credit ##
@@ -34,4 +39,6 @@ The API used with the Hue bridge has been sniffed by other people who deserve th
- http://rsmck.co.uk/hue
- http://blog.ef.net/2012/11/02/philips-hue-api.html
+Philips has since made it [publicly available](http://developers.meethue.com/).
+
There's also a ton of people who have put work into SiriProxy, thanks to them for making this possible.
57 lib/hue-entity.rb
View
@@ -0,0 +1,57 @@
+class HueEntity
+ attr_accessor :type
+ attr_accessor :name
+ attr_accessor :number
+ attr_writer :bridgeIP
+ attr_writer :username
+
+ def initialize (capturedString, bridgeIP, username)
+ @bridgeIP = bridgeIP
+ @username = username
+ response = RestClient.get("#{@bridgeIP}/api/#{@username}")
+ data = JSON.parse(response)
+ lights = data["lights"].map do |key, light|
+ {type: :light, name: light["name"].to_s, number: key.to_i}
+ end
+ lights.push({type: :group, name: "all", number: 0})
+ result = lights.select { |light| light[:name].to_s.downcase == capturedString }
+ result = result[0]
+
+ if result.empty? then return false end
+
+ @type = result[:type]
+ @number = result[:number]
+ @name = result[:name]
+ end
+
+ def power (value)
+ if self.type == :group
+ url = "#{@bridgeIP}/api/#{@username}/groups/#{@number}/action"
+ else
+ url = "#{@bridgeIP}/api/#{@username}/lights/#{@number}/state"
+ end
+ RestClient.put(url, {on: value}.to_json, content_type: :json)
+ end
+
+ def brightness (*args)
+ if args.size < 1
+ url = "#{@bridgeIP}/api/#{@username}/lights/#{@number}"
+ response = RestClient.get(url)
+ data = JSON.parse(response)
+ brightness = data["state"]["bri"].to_i
+ return brightness
+ elsif args.size == 1
+ value = args[0]
+ if (value > 254) then value = 254
+ elsif (value < 0) then value = 0
+ end
+ url = "#{@bridgeIP}/api/#{@username}/lights/#{@number}/state"
+ RestClient.put(url, {:bri => value}.to_json, content_type: :json)
+ end
+ end
+
+ def color (hue)
+ url = "#{@bridgeIP}/api/#{@username}/lights/#{@number}/state"
+ RestClient.put(url, {hue: 182*hue, sat: 254}.to_json, content_type: :json)
+ end
+end
108 lib/siriproxy-hue.rb
View
@@ -1,75 +1,61 @@
+# SiriProxy-Hue
+# https://github.com/interstateone/siriproxy-hue
+# copyright 2013, Brandon Evans
+#
+# Released under MIT License
+
+# SiriProxy Plugin Requirements
require "cora"
require "siri_objects"
require "pp"
+
require "rest_client" # HTTP requests
require "json" # Parse Hue responses
-require "matrix"
-
-################################################################################
-#
-# Hue got me babe
-#
-################################################################################
+require "matrix" # Color space transformations
+require "hue-entity"
+class SiriProxy::Plugin::Hue < SiriProxy::Plugin
+ def initialize (config)
+ @@bridgeIP = config['bridge_ip']
+ @@username = config['username']
+ @@registering = false
+ @@registered = false
+ end
-class HueEntity
- @@hueIP = "10.0.1.16"
- @@hueKey = "7dcdc2716a5c8796367968c47ad7d44c"
-
- attr_accessor :type
- attr_accessor :name
- attr_accessor :number
+ def checkRegistration
+ if @@registered then return end
- def initialize (capturedString)
- response = RestClient.get("#{@@hueIP}/api/#{@@hueKey}")
+ url = "#{@@bridgeIP}/api/#{@@username}"
+ response = RestClient.get(url)
data = JSON.parse(response)
- lights = data["lights"].map do |key, light|
- {type: :light, name: light["name"].to_s, number: key.to_i}
+ if data.kind_of?(Array)
+ data = data[0]
end
- lights.push({type: :group, name: "all", number: 0})
- result = lights.select { |light| light[:name].to_s.downcase == capturedString }
- result = result[0]
-
- if result.empty? then return false end
-
- @type = result[:type]
- @number = result[:number]
- @name = result[:name]
- end
- def power (value)
- if self.type == :group
- url = "#{@@hueIP}/api/#{@@hueKey}/groups/#{@number}/action"
+ if data.has_key? "error"
+ # Unregistered username
+ @@registering = true
+ response = ask "I just need to finish setting up: say \"Ready\" after you've pressed the link utton on your Hue bridge."
+ if response =~ /ready/i
+ url = "#{@@bridgeIP}/api"
+ data = {devicetype: "siriproxy", username: "#{@@username}"}.to_json
+ response = RestClient.post(url, data, content_type: :json)
+ request_completed
+ checkRegistration
+ end
else
- url = "#{@@hueIP}/api/#{@@hueKey}/lights/#{@number}/state"
- end
- RestClient.put(url, {on: value}.to_json, content_type: :json)
- end
-
- def brightness (*args)
- if args.size < 1
- url = "#{@@hueIP}/api/#{@@hueKey}/lights/#{@number}"
- response = RestClient.get(url)
- data = JSON.parse(response)
- brightness = data["state"]["bri"].to_i
- return brightness
- elsif args.size == 1
- value = args[0]
- if (value > 254) then value = 254
- elsif (value < 0) then value = 0
+ # Success
+ if @@registering
+ @@registering = false
+ say "Thanks, you're ready to go."
+ request_completed
+ @@registered = true
+ else
+ @@registered = true
end
- url = "#{@@hueIP}/api/#{@@hueKey}/lights/#{@number}/state"
- RestClient.put(url, {:bri => value}.to_json, content_type: :json)
end
end
- def color (hue)
- url = "#{@@hueIP}/api/#{@@hueKey}/lights/#{@number}/state"
- RestClient.put(url, {hue: 182*hue, sat: 254}.to_json, content_type: :json)
- end
-end
-
-class SiriProxy::Plugin::Hue < SiriProxy::Plugin
def parseNumbers (value)
if (value =~ /%/)
value = value.delete("%").to_i * 254 / 100 # 254 is max brightness value
@@ -82,7 +68,8 @@ def is_numeric?(obj)
# Binary state
listen_for %r/turn (on|off)(?: the)? ([a-z]*)/i do |state, entity|
- unless(matchedEntity = HueEntity.new(entity))
+ checkRegistration
+ unless(matchedEntity = HueEntity.new(entity, @@bridgeIP, @@username))
say "I couldn't find any lights by that name."
request_completed
end
@@ -105,7 +92,8 @@ def is_numeric?(obj)
# Relative brightness change
listen_for %r/turn (up|down)(?: the)? ([a-z]*)/i do |change, entity|
- unless(matchedEntity = HueEntity.new(entity))
+ checkRegistration
+ unless(matchedEntity = HueEntity.new(entity, @@bridgeIP, @@username))
say "I couldn't find any lights by that name."
request_completed
end
@@ -136,7 +124,8 @@ def is_numeric?(obj)
# Numbers (0-254) and percentages (0-100) are treated as brightness values
# Single words are used as a color query to lookup HSV values
listen_for %r/set(?: the)? ([a-z]*) to ([a-z0-9%]*)/i do |entity, value|
- unless(matchedEntity = HueEntity.new(entity))
+ checkRegistration
+ unless(matchedEntity = HueEntity.new(entity, @@bridgeIP, @@username))
say "I couldn't find any lights by that name."
request_completed
end
@@ -160,6 +149,7 @@ def is_numeric?(obj)
# Scenes
listen_for %r/make it look like a (.+)/i do |scene|
+ checkRegistration
# pull n colors, where n is the number of lights
# set each light to color[i]
request_completed
3  siriproxy-hue.gemspec
View
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
Gem::Specification.new do |s|
s.name = "siriproxy-hue"
- s.version = "0.0.1"
+ s.version = "0.0.2"
s.authors = "interstateone"
s.email = "brandon@brandonevans.ca"
s.homepage = "http://www.brandonevans.ca"
@@ -15,7 +15,6 @@ Gem::Specification.new do |s|
s.executables = `git ls-files -- bin/* 2> /dev/null`.split("\n").map{ |f| File.basename(f) }
s.require_paths = ["lib"]
- # specify any dependencies here; for example:
s.add_runtime_dependency "rest-client"
s.add_runtime_dependency "json"
end
Please sign in to comment.
Something went wrong with that request. Please try again.