huebot 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +9 -8
- data/bin/huebot +38 -8
- data/lib/huebot/bridge.rb +24 -0
- data/lib/huebot/cli.rb +33 -1
- data/lib/huebot/client.rb +131 -0
- data/lib/huebot/compiler.rb +5 -3
- data/lib/huebot/config.rb +41 -0
- data/lib/huebot/device_mapper.rb +2 -2
- data/lib/huebot/device_state.rb +7 -0
- data/lib/huebot/group.rb +23 -0
- data/lib/huebot/light.rb +23 -0
- data/lib/huebot/version.rb +1 -1
- data/lib/huebot.rb +6 -2
- metadata +12 -17
- data/lib/hue/LICENSE +0 -22
- data/lib/hue/bridge.rb +0 -140
- data/lib/hue/client.rb +0 -141
- data/lib/hue/editable_state.rb +0 -27
- data/lib/hue/errors.rb +0 -38
- data/lib/hue/group.rb +0 -181
- data/lib/hue/light.rb +0 -177
- data/lib/hue/scene.rb +0 -50
- data/lib/hue/translate_keys.rb +0 -21
- data/lib/hue/version.rb +0 -3
- data/lib/hue.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b919267fa7949b2e208ca3b62112c21f05aa1cb9e52a1cb175ab32a96e2b3411
|
4
|
+
data.tar.gz: 8ba14d33785521841fe31daff20786b6ead22592d15e3938b7b518202411b888
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 462cf2419a33689160a4471157b07302ab3fbbc48341903dde3d1c520f4cfc72a21fe6f1dc83262251270c692ad991aa04b666229f30b7218dc70d98f20ec398
|
7
|
+
data.tar.gz: 04c0e7d1fec4c384ceab06e022442ca90f9fefafbe0b15df9d6e3d8fd9db291ab16eca3af13e1db1edf0b8ea902e9d9e89bc36cdaa072e72fa956152db617c63
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Huebot
|
2
2
|
|
3
|
-
|
3
|
+
Program your Hue lights in YAML!
|
4
4
|
|
5
5
|
$ huebot run dimmer.yml --light="Office Desk"
|
6
6
|
|
@@ -34,17 +34,18 @@ The variable `$all` refers to all lights and/or groups passed in on the command
|
|
34
34
|
|
35
35
|
gem install huebot
|
36
36
|
|
37
|
-
|
37
|
+
Having trouble with Hue Bridge auto discovery? Me too. If you know your bridge's IP (and ideally have assigned it a static one), you can set it manually:
|
38
38
|
|
39
|
-
|
39
|
+
huebot set-ip <your bridge's IP>
|
40
40
|
|
41
|
-
|
41
|
+
Configuration is stored in `~/.config/huebot`.
|
42
42
|
|
43
|
-
##
|
43
|
+
## License
|
44
|
+
|
45
|
+
Huebot is licensed under the MIT license (see LICENSE file).
|
44
46
|
|
45
47
|
**TODO**
|
46
48
|
|
47
49
|
* Validate number of inputs against compiled programs
|
48
|
-
*
|
49
|
-
*
|
50
|
-
* Link to official Hue docs
|
50
|
+
* More explanation various features in Wiki
|
51
|
+
* More examples in Wiki
|
data/bin/huebot
CHANGED
@@ -9,15 +9,25 @@ require 'huebot/cli'
|
|
9
9
|
Huebot::CLI.tap { |cli|
|
10
10
|
case cli.get_cmd
|
11
11
|
when :ls
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
bridge, error = Huebot::Bridge.connect
|
13
|
+
if error
|
14
|
+
$stderr.puts error
|
15
|
+
exit 1
|
16
|
+
end
|
17
|
+
|
18
|
+
puts "Lights\n" + bridge.lights.map { |l| " #{l.id}: #{l.name}" }.join("\n") + \
|
19
|
+
"\nGroups\n" + bridge.groups.map { |g| " #{g.id}: #{g.name}" }.join("\n")
|
15
20
|
|
16
21
|
when :run
|
17
22
|
opts, sources = cli.get_input!
|
18
23
|
|
19
|
-
|
20
|
-
|
24
|
+
bridge, error = Huebot::Bridge.connect
|
25
|
+
if error
|
26
|
+
$stderr.puts error
|
27
|
+
exit 1
|
28
|
+
end
|
29
|
+
|
30
|
+
device_mapper = Huebot::DeviceMapper.new(bridge, opts.inputs)
|
21
31
|
compiler = Huebot::Compiler.new(device_mapper)
|
22
32
|
|
23
33
|
programs = sources.map { |src|
|
@@ -26,14 +36,19 @@ Huebot::CLI.tap { |cli|
|
|
26
36
|
found_errors, _found_warnings = cli.check! programs, $stderr
|
27
37
|
exit 1 if found_errors
|
28
38
|
|
29
|
-
bot = Huebot::Bot.new(
|
39
|
+
bot = Huebot::Bot.new(bridge)
|
30
40
|
programs.each { |prog| bot.execute prog }
|
31
41
|
|
32
42
|
when :check
|
33
43
|
opts, sources = cli.get_input!
|
34
44
|
|
35
|
-
|
36
|
-
|
45
|
+
bridge, error = Huebot::Bridge.connect
|
46
|
+
if error
|
47
|
+
$stderr.puts error
|
48
|
+
exit 1
|
49
|
+
end
|
50
|
+
|
51
|
+
device_mapper = Huebot::DeviceMapper.new(bridge, opts.inputs)
|
37
52
|
compiler = Huebot::Compiler.new(device_mapper)
|
38
53
|
|
39
54
|
programs = sources.map { |src|
|
@@ -43,6 +58,21 @@ Huebot::CLI.tap { |cli|
|
|
43
58
|
# TODO validate NUMBER of inputs against each program
|
44
59
|
exit (found_errors || found_warnings) ? 1 : 0
|
45
60
|
|
61
|
+
when :"set-ip"
|
62
|
+
ip = cli.get_args(num: 1).first
|
63
|
+
config = Huebot::Config.new
|
64
|
+
config["ip"] = ip
|
65
|
+
|
66
|
+
when :"clear-ip"
|
67
|
+
cli.get_args(num: 0)
|
68
|
+
config = Huebot::Config.new
|
69
|
+
config["ip"] = nil
|
70
|
+
|
71
|
+
when :unregister
|
72
|
+
cli.get_args(num: 0)
|
73
|
+
config = Huebot::Config.new
|
74
|
+
config.clear
|
75
|
+
|
46
76
|
else cli.help!
|
47
77
|
end
|
48
78
|
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Huebot
|
2
|
+
class Bridge
|
3
|
+
def self.connect(config = Huebot::Config.new)
|
4
|
+
client = Client.new(config)
|
5
|
+
error = client.connect
|
6
|
+
return nil, error if error
|
7
|
+
return new(client)
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :client
|
11
|
+
|
12
|
+
def initialize(client)
|
13
|
+
@client = client
|
14
|
+
end
|
15
|
+
|
16
|
+
def lights
|
17
|
+
client.get!("/lights").map { |(id, attrs)| Light.new(client, id, attrs) }
|
18
|
+
end
|
19
|
+
|
20
|
+
def groups
|
21
|
+
client.get!("/groups").map { |(id, attrs)| Group.new(client, id, attrs) }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/huebot/cli.rb
CHANGED
@@ -23,6 +23,31 @@ module Huebot
|
|
23
23
|
ARGV[0].to_s.to_sym
|
24
24
|
end
|
25
25
|
|
26
|
+
def self.get_args(min: nil, max: nil, num: nil)
|
27
|
+
args = ARGV[1..]
|
28
|
+
if num
|
29
|
+
if num != args.size
|
30
|
+
$stderr.puts "Expected #{num} args, found #{args.size}"
|
31
|
+
exit 1
|
32
|
+
end
|
33
|
+
elsif min and max
|
34
|
+
if args.size < min or args.size > max
|
35
|
+
$stderr.puts "Expected #{min}-#{max} args, found #{args.size}"
|
36
|
+
end
|
37
|
+
elsif min
|
38
|
+
if args.size < min
|
39
|
+
$stderr.puts "Expected at least #{num} args, found #{args.size}"
|
40
|
+
exit 1
|
41
|
+
end
|
42
|
+
elsif max
|
43
|
+
if args.size > max
|
44
|
+
$stderr.puts "Expected no more than #{num} args, found #{args.size}"
|
45
|
+
exit 1
|
46
|
+
end
|
47
|
+
end
|
48
|
+
args
|
49
|
+
end
|
50
|
+
|
26
51
|
#
|
27
52
|
# Parses and returns input from the CLI. Serious errors might result in the program exiting.
|
28
53
|
#
|
@@ -37,7 +62,7 @@ module Huebot
|
|
37
62
|
if files.empty? and !options.read_stdin
|
38
63
|
puts parser.help
|
39
64
|
exit 1
|
40
|
-
elsif (bad_paths = files.select { |p| !File.
|
65
|
+
elsif (bad_paths = files.select { |p| !File.exist? p }).any?
|
41
66
|
$stderr.puts "Cannot find #{bad_paths.join ', '}"
|
42
67
|
exit 1
|
43
68
|
else
|
@@ -107,6 +132,13 @@ Run program(s):
|
|
107
132
|
Validate programs and inputs:
|
108
133
|
huebot check file1.yml [file2.yml [file3.yml ...]] [options]
|
109
134
|
|
135
|
+
Manually set/clear the IP for your Hue Bridge (useful when on a VPN):
|
136
|
+
huebot set-ip 192.168.1.20
|
137
|
+
huebot clear-ip
|
138
|
+
|
139
|
+
Clear all connection config:
|
140
|
+
huebot unregister
|
141
|
+
|
110
142
|
Options:
|
111
143
|
).strip
|
112
144
|
opts.on("-lLIGHT", "--light=LIGHT", "Light ID or name") { |l| options.inputs << LightInput.new(l) }
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Huebot
|
6
|
+
class Client
|
7
|
+
DISCOVERY_URI = URI(ENV["HUE_DISCOVERY_API"] || "https://discovery.meethue.com/")
|
8
|
+
Bridge = Struct.new(:id, :ip)
|
9
|
+
|
10
|
+
attr_reader :config
|
11
|
+
|
12
|
+
def initialize(config = Huebot::Config.new)
|
13
|
+
@config = config
|
14
|
+
@ip = config["ip"] # NOTE will usually be null
|
15
|
+
@username = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def connect
|
19
|
+
if config["ip"]
|
20
|
+
@ip = config["ip"]
|
21
|
+
elsif config["id"]
|
22
|
+
@ip = bridges.detect { |b| b.id == id }&.ip
|
23
|
+
return "Unable to find Hue Bridge '#{config["id"]}' on your network" if @ip.nil?
|
24
|
+
else
|
25
|
+
bridge = bridges.first
|
26
|
+
return "Unable to find a Hue Bridge on your network" if bridge.nil?
|
27
|
+
config["id"] = bridge.id
|
28
|
+
@ip = bridge.ip
|
29
|
+
end
|
30
|
+
|
31
|
+
if config["username"]
|
32
|
+
if valid_username? config["username"]
|
33
|
+
@username = config["username"]
|
34
|
+
else
|
35
|
+
return "Invalid Hue Bridge username '#{config["username"]}'"
|
36
|
+
end
|
37
|
+
else
|
38
|
+
username, error = register
|
39
|
+
return error if error
|
40
|
+
config["username"] = @username = username
|
41
|
+
end
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def get!(path)
|
46
|
+
resp, error = get path
|
47
|
+
raise error if error
|
48
|
+
resp
|
49
|
+
end
|
50
|
+
|
51
|
+
def get(path)
|
52
|
+
url = "http://#{@ip}/api"
|
53
|
+
url << "/#{@username}" if @username
|
54
|
+
url << path
|
55
|
+
req = Net::HTTP::Get.new(URI(url))
|
56
|
+
req_json req
|
57
|
+
end
|
58
|
+
|
59
|
+
def post!(path, body)
|
60
|
+
resp, error = post path, body
|
61
|
+
raise error if error
|
62
|
+
resp
|
63
|
+
end
|
64
|
+
|
65
|
+
def post(path, body)
|
66
|
+
url = "http://#{@ip}/api"
|
67
|
+
url << "/#{@username}" if @username
|
68
|
+
url << path
|
69
|
+
req = Net::HTTP::Post.new(URI(url))
|
70
|
+
req["Content-Type"] = "application/json"
|
71
|
+
req.body = body.to_json
|
72
|
+
req_json req
|
73
|
+
end
|
74
|
+
|
75
|
+
def put!(path, body)
|
76
|
+
resp, error = put path, body
|
77
|
+
raise error if error
|
78
|
+
resp
|
79
|
+
end
|
80
|
+
|
81
|
+
def put(path, body)
|
82
|
+
url = "http://#{@ip}/api"
|
83
|
+
url << "/#{@username}" if @username
|
84
|
+
url << path
|
85
|
+
req = Net::HTTP::Put.new(URI(url))
|
86
|
+
req["Content-Type"] = "application/json"
|
87
|
+
req.body = body.to_json
|
88
|
+
req_json req
|
89
|
+
end
|
90
|
+
|
91
|
+
def req_json(req)
|
92
|
+
resp = Net::HTTP.start req.uri.host, req.uri.port, {use_ssl: false} do |http|
|
93
|
+
http.request req
|
94
|
+
end
|
95
|
+
case resp.code.to_i
|
96
|
+
when 200..201
|
97
|
+
data = JSON.parse(resp.body)
|
98
|
+
if data[0] and (error = data[0]["error"])
|
99
|
+
return nil, error.fetch("description")
|
100
|
+
else
|
101
|
+
return data, nil
|
102
|
+
end
|
103
|
+
else
|
104
|
+
raise "Unexpected response from Bridge (#{resp.code}): #{resp.body}"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def bridges
|
109
|
+
req = Net::HTTP::Get.new(DISCOVERY_URI)
|
110
|
+
resp = Net::HTTP.start req.uri.host, req.uri.port, {use_ssl: true} do |http|
|
111
|
+
http.request req
|
112
|
+
end
|
113
|
+
JSON.parse(resp.body).map { |x|
|
114
|
+
Bridge.new(x.fetch("id"), x.fetch("internalipaddress"))
|
115
|
+
}
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
def valid_username?(username)
|
121
|
+
_resp, error = get("/#{username}")
|
122
|
+
!error
|
123
|
+
end
|
124
|
+
|
125
|
+
def register
|
126
|
+
resp, error = post "/", {"devicetype": "huebot"}
|
127
|
+
return nil, error if error
|
128
|
+
resp[0].fetch("success").fetch("username")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
data/lib/huebot/compiler.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module Huebot
|
2
2
|
class Compiler
|
3
|
+
DEVICE_FIELDS = %i(light lights group groups device devices).freeze
|
4
|
+
|
3
5
|
def initialize(device_mapper)
|
4
6
|
@device_mapper = device_mapper
|
5
7
|
end
|
@@ -130,9 +132,9 @@ module Huebot
|
|
130
132
|
end
|
131
133
|
state[:transitiontime] = t.delete("time") || t.delete(:time) || t.delete("transitiontime") || t.delete(:transitiontime) || 4
|
132
134
|
|
133
|
-
transition.state = t.merge(state).
|
134
|
-
|
135
|
-
|
135
|
+
transition.state = t.merge(state).each_with_object({}) { |(key, val), obj|
|
136
|
+
key = key.to_sym
|
137
|
+
obj[key] = val unless DEVICE_FIELDS.include? key
|
136
138
|
}
|
137
139
|
return errors, warnings, transition
|
138
140
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Huebot
|
5
|
+
class Config
|
6
|
+
def initialize(path = "~/.config/huebot")
|
7
|
+
@path = File.expand_path(path)
|
8
|
+
@dir = File.dirname(@path)
|
9
|
+
@dir_exists = File.exist? @dir
|
10
|
+
@config = File.exist?(@path) ? YAML.load_file(@path) : {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def [](attr)
|
14
|
+
@config[attr.to_s]
|
15
|
+
end
|
16
|
+
|
17
|
+
def []=(attr, val)
|
18
|
+
if val.nil?
|
19
|
+
@config.delete(attr.to_s)
|
20
|
+
else
|
21
|
+
@config[attr.to_s] = val
|
22
|
+
end
|
23
|
+
write
|
24
|
+
end
|
25
|
+
|
26
|
+
def clear
|
27
|
+
@config.clear
|
28
|
+
write
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def write
|
34
|
+
unless @dir_exists
|
35
|
+
FileUtils.mkdir_p @dir
|
36
|
+
@dir_exists = true
|
37
|
+
end
|
38
|
+
File.write(@path, YAML.dump(@config))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/huebot/device_mapper.rb
CHANGED
@@ -2,8 +2,8 @@ module Huebot
|
|
2
2
|
class DeviceMapper
|
3
3
|
Unmapped = Class.new(StandardError)
|
4
4
|
|
5
|
-
def initialize(
|
6
|
-
all_lights, all_groups =
|
5
|
+
def initialize(bridge, inputs = [])
|
6
|
+
all_lights, all_groups = bridge.lights, bridge.groups
|
7
7
|
|
8
8
|
@lights_by_id = all_lights.reduce({}) { |a, l| a[l.id] = l; a }
|
9
9
|
@lights_by_name = all_lights.reduce({}) { |a, l| a[l.name] = l; a }
|
data/lib/huebot/group.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Huebot
|
2
|
+
class Group
|
3
|
+
include DeviceState
|
4
|
+
attr_reader :client, :id, :name
|
5
|
+
|
6
|
+
def initialize(client, id, attrs)
|
7
|
+
@client = client
|
8
|
+
@id = id
|
9
|
+
@name = attrs.fetch("name")
|
10
|
+
@attrs = attrs
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def state_url
|
16
|
+
url "/action"
|
17
|
+
end
|
18
|
+
|
19
|
+
def url(path)
|
20
|
+
"/groups/#{id}#{path}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/huebot/light.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Huebot
|
2
|
+
class Light
|
3
|
+
include DeviceState
|
4
|
+
attr_reader :client, :id, :name
|
5
|
+
|
6
|
+
def initialize(client, id, attrs)
|
7
|
+
@client = client
|
8
|
+
@id = id
|
9
|
+
@name = attrs.fetch("name")
|
10
|
+
@attrs = attrs
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def state_url
|
16
|
+
url "/state"
|
17
|
+
end
|
18
|
+
|
19
|
+
def url(path)
|
20
|
+
"/lights/#{id}#{path}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/huebot/version.rb
CHANGED
data/lib/huebot.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
-
require 'hue'
|
2
|
-
|
3
1
|
module Huebot
|
2
|
+
autoload :Config, 'huebot/config'
|
3
|
+
autoload :Client, 'huebot/client'
|
4
|
+
autoload :Bridge, 'huebot/bridge'
|
5
|
+
autoload :DeviceState, 'huebot/device_state'
|
6
|
+
autoload :Light, 'huebot/light'
|
7
|
+
autoload :Group, 'huebot/group'
|
4
8
|
autoload :DeviceMapper, 'huebot/device_mapper'
|
5
9
|
autoload :Program, 'huebot/program'
|
6
10
|
autoload :Compiler, 'huebot/compiler'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: huebot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jordan Hollinger
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-12-08 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Declare and run YAML programs for Philips Hue devices
|
14
14
|
email: jordan.hollinger@gmail.com
|
@@ -19,29 +19,24 @@ extra_rdoc_files: []
|
|
19
19
|
files:
|
20
20
|
- README.md
|
21
21
|
- bin/huebot
|
22
|
-
- lib/hue.rb
|
23
|
-
- lib/hue/LICENSE
|
24
|
-
- lib/hue/bridge.rb
|
25
|
-
- lib/hue/client.rb
|
26
|
-
- lib/hue/editable_state.rb
|
27
|
-
- lib/hue/errors.rb
|
28
|
-
- lib/hue/group.rb
|
29
|
-
- lib/hue/light.rb
|
30
|
-
- lib/hue/scene.rb
|
31
|
-
- lib/hue/translate_keys.rb
|
32
|
-
- lib/hue/version.rb
|
33
22
|
- lib/huebot.rb
|
34
23
|
- lib/huebot/bot.rb
|
24
|
+
- lib/huebot/bridge.rb
|
35
25
|
- lib/huebot/cli.rb
|
26
|
+
- lib/huebot/client.rb
|
36
27
|
- lib/huebot/compiler.rb
|
28
|
+
- lib/huebot/config.rb
|
37
29
|
- lib/huebot/device_mapper.rb
|
30
|
+
- lib/huebot/device_state.rb
|
31
|
+
- lib/huebot/group.rb
|
32
|
+
- lib/huebot/light.rb
|
38
33
|
- lib/huebot/program.rb
|
39
34
|
- lib/huebot/version.rb
|
40
35
|
homepage: https://github.com/jhollinger/huebot
|
41
36
|
licenses:
|
42
37
|
- MIT
|
43
38
|
metadata: {}
|
44
|
-
post_install_message:
|
39
|
+
post_install_message:
|
45
40
|
rdoc_options: []
|
46
41
|
require_paths:
|
47
42
|
- lib
|
@@ -56,8 +51,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
56
51
|
- !ruby/object:Gem::Version
|
57
52
|
version: '0'
|
58
53
|
requirements: []
|
59
|
-
rubygems_version: 3.
|
60
|
-
signing_key:
|
54
|
+
rubygems_version: 3.4.1
|
55
|
+
signing_key:
|
61
56
|
specification_version: 4
|
62
57
|
summary: Orchestration for Hue devices
|
63
58
|
test_files: []
|
data/lib/hue/LICENSE
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
Copyright (c) 2013-2014 Sam Soffes, http://soff.es
|
2
|
-
|
3
|
-
MIT License
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
-
a copy of this software and associated documentation files (the
|
7
|
-
"Software"), to deal in the Software without restriction, including
|
8
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
-
permit persons to whom the Software is furnished to do so, subject to
|
11
|
-
the following conditions:
|
12
|
-
|
13
|
-
The above copyright notice and this permission notice shall be
|
14
|
-
included in all copies or substantial portions of the Software.
|
15
|
-
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|