hue 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af74df93c5514679bab0613c9c6c87b0a0dfae19b919fc903ad42a8fafe9b681
4
- data.tar.gz: 0afb9bd5b7ee11be0a1dce6b56846c6d13fa7cd9a9b67e2f9c8014c8d03f0fb7
3
+ metadata.gz: 17b9710dcfb0defef023c1adb4c4da4ca86fddc6f2e6c0d971bcb562c57ec61a
4
+ data.tar.gz: 8d8afd006ca7892d74f33af84f4040aedd0718b13583e1708a6994bb7803c3d9
5
5
  SHA512:
6
- metadata.gz: 00f64a5fdad18722af090747e6a2dfe2a5fefb556bcd634ee7b498f54df80e23e94975c295a2925a46cf2166e88df0af07dee1999e26446f7e42e66ebbc8778b
7
- data.tar.gz: f54f5552bceb7456b0a1d6ccdc29f7ca3cb01636231d83a5f0d7d93b907defce6bfbfcb0e2f96444e49543fbb85f7cda66586f72eedaea912c7a18f5ededb570
6
+ metadata.gz: 8d3a2e81c450c2d1dd5c94ade3cf146ea4f56f4102f710051c54185902c388f9c9494a6f597f3f0ee05b59d0b0ade9ba837c2a7983df9679ce14ea34dd07e9eb
7
+ data.tar.gz: eea449790732dbcfcd0795f1e01af3d6d1a19b800c3b41404fe0bd1a12a76fa706f59269f90320365dde650c6425811fca9bd0ea38558945e8d8c0800badcdc4
@@ -2,13 +2,28 @@ name: Tests
2
2
  on: [push]
3
3
  jobs:
4
4
  test:
5
- name: Test Swift Package
5
+ name: Test
6
6
  runs-on: ubuntu-latest
7
7
  timeout-minutes: 5
8
8
  steps:
9
- - uses: actions/checkout@v1
10
- - uses: actions/setup-ruby@v1
11
- - name: 'Install Dependencies'
12
- run: sudo apt-get install libcurl4-openssl-dev && gem install bundler && bundle install
13
- - name: 'Test'
9
+ - name: Checkout
10
+ uses: actions/checkout@v4
11
+ - name: Setup Ruby
12
+ uses: ruby/setup-ruby@v1
13
+ with:
14
+ bundler-cache: true
15
+ - name: Test
14
16
  run: bundle exec rake test
17
+ lint:
18
+ name: Lint
19
+ runs-on: ubuntu-latest
20
+ timeout-minutes: 5
21
+ steps:
22
+ - name: Checkout
23
+ uses: actions/checkout@v4
24
+ - name: Setup Ruby
25
+ uses: ruby/setup-ruby@v1
26
+ with:
27
+ bundler-cache: true
28
+ - name: Test
29
+ run: bundle exec rake standard
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ .DS_Store
1
2
  *.gem
2
3
  *.rbc
3
4
  .bundle
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.2.2
data/Gemfile CHANGED
@@ -1,5 +1,8 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rake'
5
+ gem "rake", "~> 13.0"
6
+ gem "minitest", "~> 5.0"
7
+ gem "standard", "~> 1.3"
8
+ gem "webmock", "~> 3.19"
data/Rakefile CHANGED
@@ -1,10 +1,12 @@
1
- require 'bundler/gem_tasks'
2
- require 'rake/testtask'
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
3
 
4
4
  Rake::TestTask.new(:test) do |t|
5
- t.libs << 'test'
6
- t.libs << 'lib'
7
- t.test_files = FileList['test/**/*_test.rb']
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
8
  end
9
9
 
10
- task :default => :test
10
+ require "standard/rake"
11
+
12
+ task default: :test
data/bin/console ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'hue'
5
+
6
+ require 'irb'
7
+ IRB.start(__FILE__)
data/hue.gemspec CHANGED
@@ -1,28 +1,23 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ lib = File.expand_path("../lib", __FILE__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'hue/version'
3
+ require "hue/version"
5
4
 
6
5
  Gem::Specification.new do |spec|
7
- spec.name = 'hue'
8
- spec.version = Hue::VERSION
9
- spec.authors = ['Sam Soffes']
10
- spec.email = ['sam@soff.es']
11
- spec.description = 'Work with Philips Hue light bulbs.'
12
- spec.summary = 'Work with Philips Hue light bulbs from Ruby.'
13
- spec.homepage = 'https://github.com/soffes/hue'
14
- spec.license = 'MIT'
6
+ spec.name = "hue"
7
+ spec.version = Hue::VERSION
8
+ spec.authors = ["Sam Soffes"]
9
+ spec.email = ["sam@soff.es"]
10
+ spec.description = "Work with Philips Hue light bulbs."
11
+ spec.summary = "Work with Philips Hue light bulbs from Ruby."
12
+ spec.homepage = "https://github.com/soffes/hue"
13
+ spec.license = "MIT"
15
14
 
16
- spec.files = `git ls-files`.split($/)
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ['lib']
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.require_paths = ["lib"]
20
18
 
21
- spec.required_ruby_version = '>= 2.1.0'
22
- spec.add_dependency 'thor'
23
- spec.add_dependency 'json'
24
- spec.add_dependency 'log_switch', '0.4.0'
25
- spec.add_dependency 'curb'
26
- spec.add_development_dependency 'minitest', '~> 5.0'
27
- spec.add_development_dependency 'webmock'
19
+ spec.required_ruby_version = ">= 2.1.0"
20
+ spec.add_dependency "thor"
21
+ spec.add_dependency "json"
22
+ spec.add_dependency "color_conversion"
28
23
  end
data/lib/hue/bridge.rb CHANGED
@@ -46,21 +46,21 @@ module Hue
46
46
  # Current time stored on the bridge.
47
47
  def utc
48
48
  json = get_configuration
49
- DateTime.parse(json['utc'])
49
+ DateTime.parse(json["utc"])
50
50
  end
51
51
 
52
52
  # Indicates whether the link button has been pressed within the last 30
53
53
  # seconds.
54
54
  def link_button_pressed?
55
55
  json = get_configuration
56
- json['linkbutton']
56
+ json["linkbutton"]
57
57
  end
58
58
 
59
59
  # This indicates whether the bridge is registered to synchronize data with a
60
60
  # portal account.
61
61
  def has_portal_services?
62
62
  json = get_configuration
63
- json['portalservices']
63
+ json["portalservices"]
64
64
  end
65
65
 
66
66
  def refresh
@@ -74,7 +74,7 @@ module Hue
74
74
  def lights
75
75
  @lights ||= begin
76
76
  json = JSON(Net::HTTP.get(URI.parse(base_url)))
77
- json['lights'].map do |key, value|
77
+ json["lights"].map do |key, value|
78
78
  Light.new(@client, self, key, value)
79
79
  end
80
80
  end
@@ -84,7 +84,7 @@ module Hue
84
84
  uri = URI.parse("#{base_url}/lights")
85
85
  http = Net::HTTP.new(uri.host)
86
86
  response = http.request_post(uri.path, nil)
87
- (response.body).first
87
+ response.body.first
88
88
  end
89
89
 
90
90
  def groups
@@ -105,27 +105,27 @@ module Hue
105
105
  end
106
106
  end
107
107
 
108
- private
108
+ private
109
109
 
110
110
  KEYS_MAP = {
111
- :id => :id,
112
- :ip => :internalipaddress,
113
- :name => :name,
114
- :proxy_port => :proxyport,
115
- :software_update => :swupdate,
116
- :ip_whitelist => :whitelist,
117
- :software_version => :swversion,
118
- :proxy_address => :proxyaddress,
119
- :mac_address => :macaddress,
120
- :network_mask => :netmask,
121
- :portal_services => :portalservices,
111
+ id: :id,
112
+ ip: :internalipaddress,
113
+ name: :name,
114
+ proxy_port: :proxyport,
115
+ software_update: :swupdate,
116
+ ip_whitelist: :whitelist,
117
+ software_version: :swversion,
118
+ proxy_address: :proxyaddress,
119
+ mac_address: :macaddress,
120
+ network_mask: :netmask,
121
+ portal_services: :portalservices
122
122
  }
123
123
 
124
124
  def unpack(hash)
125
125
  KEYS_MAP.each do |local_key, remote_key|
126
126
  value = hash[remote_key.to_s]
127
127
  next unless value
128
- instance_variable_set("@#{local_key}", value)
128
+ instance_variable_set(:"@#{local_key}", value)
129
129
  end
130
130
  end
131
131
 
data/lib/hue/cli.rb CHANGED
@@ -1,67 +1,67 @@
1
- require 'thor'
1
+ require "thor"
2
2
 
3
3
  module Hue
4
4
  class Cli < Thor
5
- desc 'lights', 'Find all of the lights on your network'
5
+ desc "lights", "Find all of the lights on your network"
6
6
  def lights
7
7
  client.lights.each do |light|
8
8
  puts light.id.to_s.ljust(6) + light.name
9
9
  end
10
10
  end
11
11
 
12
- desc 'add LIGHTS', 'Search for new lights'
12
+ desc "add LIGHTS", "Search for new lights"
13
13
  def add(thing)
14
14
  case thing
15
- when 'lights'
15
+ when "lights"
16
16
  client.add_lights
17
17
  end
18
18
  end
19
19
 
20
- desc 'light ID STATE [COLOR]', 'Access a light'
20
+ desc "light ID STATE [COLOR]", "Access a light"
21
21
  long_desc <<-LONGDESC
22
22
  Examples: \n
23
23
  hue all on \n
24
24
  hue all off \n
25
25
  hue all --hue 12345 \n
26
- hue all --bri 25 \n
27
- hue all --hue 50000 --bri 200 --sat 240 \n
26
+ hue all --brightness 25 \n
27
+ hue all --hue 50000 --brightness 200 --saturation 240 \n
28
28
  hue all --alert lselect \n
29
29
  LONGDESC
30
- option :hue, :type => :numeric
31
- option :sat, :type => :numeric, :aliases => '--saturation'
32
- option :bri, :type => :numeric, :aliases => '--brightness'
33
- option :alert, :type => :string
34
- desc 'all STATE', 'Send commands to all lights'
35
- def all(state = 'on')
30
+ option :hue, type: :numeric
31
+ option :sat, type: :numeric, aliases: "--saturation"
32
+ option :bri, type: :numeric, aliases: "--brightness"
33
+ option :alert, type: :string
34
+ desc "all STATE", "Send commands to all lights"
35
+ def all(state = "on")
36
36
  body = options.dup
37
- body[:on] = state == 'on'
37
+ body[:on] = state == "on"
38
38
  client.lights.each do |light|
39
39
  puts light.set_state body
40
40
  end
41
41
  end
42
42
 
43
- desc 'light ID STATE [COLOR]', 'Access a light'
43
+ desc "light ID STATE [COLOR]", "Access a light"
44
44
  long_desc <<-LONGDESC
45
45
  Examples: \n
46
46
  hue light 1 on --hue 12345 \n
47
- hue light 1 --bri 25 \n
47
+ hue light 1 --brightness 25 \n
48
48
  hue light 1 --alert lselect \n
49
49
  hue light 1 off
50
50
  LONGDESC
51
- option :hue, :type => :numeric
52
- option :sat, :type => :numeric, :aliases => '--saturation'
53
- option :brightness, :type => :numeric, :aliases => '--brightness'
54
- option :alert, :type => :string
51
+ option :hue, type: :numeric
52
+ option :sat, type: :numeric, aliases: "--saturation"
53
+ option :bri, type: :numeric, aliases: "--brightness"
54
+ option :alert, type: :string
55
55
  def light(id, state = nil)
56
56
  light = client.light(id)
57
57
  puts light.name
58
58
 
59
59
  body = options.dup
60
- body[:on] = (state == 'on' || !(state == 'off'))
60
+ body[:on] = (state == "on" || !(state == "off"))
61
61
  puts light.set_state(body) if body.length > 0
62
62
  end
63
63
 
64
- desc 'groups', 'Find all light groups on your network'
64
+ desc "groups", "Find all light groups on your network"
65
65
  def groups
66
66
  client.groups.each do |group|
67
67
  puts group.id.to_s.ljust(6) + group.name
@@ -71,28 +71,28 @@ module Hue
71
71
  end
72
72
  end
73
73
 
74
- desc 'group ID STATE [COLOR]', 'Update a group of lights'
74
+ desc "group ID STATE [COLOR]", "Update a group of lights"
75
75
  long_desc <<-LONGDESC
76
76
  Examples: \n
77
77
  hue groups 1 on --hue 12345
78
- hue groups 1 --bri 25
78
+ hue groups 1 --brightness 25
79
79
  hue groups 1 --alert lselect
80
80
  hue groups 1 off
81
81
  LONGDESC
82
- option :hue, :type => :numeric
83
- option :sat, :type => :numeric, :aliases => '--saturation'
84
- option :brightness, :type => :numeric, :aliases => '--brightness'
85
- option :alert, :type => :string
82
+ option :hue, type: :numeric
83
+ option :sat, type: :numeric, aliases: "--saturation"
84
+ option :bri, type: :numeric, aliases: "--brightness"
85
+ option :alert, type: :string
86
86
  def group(id, state = nil)
87
87
  group = client.group(id)
88
88
  puts group.name
89
89
 
90
90
  body = options.dup
91
- body[:on] = (state == 'on' || !(state == 'off'))
91
+ body[:on] = (state == "on" || !(state == "off"))
92
92
  puts group.set_state(body) if body.length > 0
93
93
  end
94
94
 
95
- private
95
+ private
96
96
 
97
97
  def client
98
98
  @client ||= Hue::Client.new
data/lib/hue/client.rb CHANGED
@@ -1,7 +1,6 @@
1
- require 'net/http'
2
- require 'json'
3
- require 'resolv'
4
- require 'curb'
1
+ require "net/http"
2
+ require "json"
3
+ require "resolv"
5
4
 
6
5
  module Hue
7
6
  class Client
@@ -24,11 +23,11 @@ module Hue
24
23
  end
25
24
 
26
25
  def bridge
27
- @bridge_id = find_bridge_id unless @bridge_id
28
- if @bridge_id
29
- bridge = bridges.select { |b| b.id == @bridge_id }.first
26
+ @bridge_id ||= find_bridge_id
27
+ bridge = if @bridge_id
28
+ bridges.find { |b| b.id == @bridge_id }
30
29
  else
31
- bridge = bridges.first
30
+ bridges.first
32
31
  end
33
32
  raise NoBridgeFound unless bridge
34
33
  bridge
@@ -53,7 +52,7 @@ module Hue
53
52
 
54
53
  def light(id)
55
54
  id = id.to_s
56
- lights.select { |l| l.id == id }.first
55
+ lights.find { |l| l.id == id }
57
56
  end
58
57
 
59
58
  def groups
@@ -64,7 +63,7 @@ module Hue
64
63
  return Group.new(self, bridge) if id.nil?
65
64
 
66
65
  id = id.to_s
67
- groups.select { |g| g.id == id }.first
66
+ groups.find { |g| g.id == id }
68
67
  end
69
68
 
70
69
  def scenes
@@ -73,18 +72,18 @@ module Hue
73
72
 
74
73
  def scene(id)
75
74
  id = id.to_s
76
- scenes.select { |s| s.id == id }.first
75
+ scenes.find { |s| s.id == id }
77
76
  end
78
77
 
79
78
  private
80
79
 
81
80
  def find_username
82
- return ENV['HUE_USERNAME'] if ENV['HUE_USERNAME']
81
+ return ENV["HUE_USERNAME"] if ENV["HUE_USERNAME"]
83
82
 
84
- json = JSON(File.read(File.expand_path('~/.hue')))
85
- json['username']
83
+ json = JSON(File.read(File.expand_path("~/.hue")))
84
+ json["username"]
86
85
  rescue
87
- return nil
86
+ nil
88
87
  end
89
88
 
90
89
  def validate_user
@@ -94,38 +93,38 @@ module Hue
94
93
  response = response.first
95
94
  end
96
95
 
97
- if error = response['error']
96
+ if (error = response["error"])
98
97
  raise get_error(error)
99
98
  end
100
99
 
101
- response['success']
100
+ response["success"]
102
101
  end
103
102
 
104
103
  def register_user
105
104
  body = JSON.dump({
106
- devicetype: 'Ruby'
105
+ devicetype: "Ruby"
107
106
  })
108
107
 
109
108
  uri = URI.parse("http://#{bridge.ip}/api")
110
109
  http = Net::HTTP.new(uri.host)
111
110
  response = JSON(http.request_post(uri.path, body).body).first
112
111
 
113
- if error = response['error']
112
+ if (error = response["error"])
114
113
  raise get_error(error)
115
114
  end
116
115
 
117
- if @username = response['success']['username']
118
- File.write(File.expand_path('~/.hue'), JSON.dump({username: @username}))
116
+ if (@username = response["success"]["username"])
117
+ File.write(File.expand_path("~/.hue"), JSON.dump({username: @username}))
119
118
  end
120
119
  end
121
120
 
122
121
  def find_bridge_id
123
- return ENV['HUE_BRIDGE_ID'] if ENV['HUE_BRIDGE_ID']
122
+ return ENV["HUE_BRIDGE_ID"] if ENV["HUE_BRIDGE_ID"]
124
123
 
125
- json = JSON(File.read(File.expand_path('~/.hue')))
126
- json['bridge_id']
124
+ json = JSON(File.read(File.expand_path("~/.hue")))
125
+ json["bridge_id"]
127
126
  rescue
128
- return nil
127
+ nil
129
128
  end
130
129
 
131
130
  def discovery_mdns(bs)
@@ -136,8 +135,8 @@ module Hue
136
135
  bridge_target = resolver.getresource(bridge_ptr.name, Resolv::DNS::Resource::IN::SRV).target
137
136
 
138
137
  bridge_hash = {
139
- 'id' => resolver.getresource(bridge_ptr.name, Resolv::DNS::Resource::IN::TXT).strings[0].split('=')[1],
140
- 'internalipaddress' => resolver.getresource(bridge_target, Resolv::DNS::Resource::IN::A).address
138
+ "id" => resolver.getresource(bridge_ptr.name, Resolv::DNS::Resource::IN::TXT).strings[0].split("=")[1],
139
+ "internalipaddress" => resolver.getresource(bridge_target, Resolv::DNS::Resource::IN::A).address
141
140
  }
142
141
 
143
142
  bs << Bridge.new(self, bridge_hash)
@@ -145,20 +144,18 @@ module Hue
145
144
  end
146
145
 
147
146
  def discovery_meethue(bs)
148
- easy = Curl::Easy.new
149
- easy.follow_location = true
150
- easy.max_redirects = 10
151
- easy.url = 'https://discovery.meethue.com/'
152
- easy.perform
153
- JSON(easy.body).each do |hash|
147
+ uri = URI("https://discovery.meethue.com/")
148
+ response = Net::HTTP.get(uri)
149
+
150
+ JSON(response).each do |hash|
154
151
  bs << Bridge.new(self, hash)
155
152
  end
156
153
  end
157
154
 
158
155
  def get_error(error)
159
156
  # Find error class and return instance
160
- klass = Hue::ERROR_MAP[error['type']] || UnknownError unless klass
161
- klass.new(error['description'])
157
+ klass ||= Hue::ERROR_MAP[error["type"]] || UnknownError
158
+ klass.new(error["description"])
162
159
  end
163
160
  end
164
161
  end
@@ -1,7 +1,13 @@
1
+ require "color_conversion"
2
+
1
3
  module Hue
2
4
  module EditableState
5
+ HUE_RANGE = 0..65535
6
+ SATURATION_RANGE = 0..254
7
+ BRIGHTNESS_RANGE = 0..254
8
+
3
9
  def on?
4
- @state['on']
10
+ @on || false
5
11
  end
6
12
 
7
13
  def on!
@@ -12,16 +18,47 @@ module Hue
12
18
  self.on = false
13
19
  end
14
20
 
15
- %w{on hue saturation brightness color_temperature alert effect}.each do |key|
16
- define_method "#{key}=".to_sym do |value|
21
+ # Turn the light on if it's off and vice versa
22
+ def toggle!
23
+ if @on
24
+ off!
25
+ else
26
+ on!
27
+ end
28
+ end
29
+
30
+ %w[on hue saturation brightness color_temperature alert effect].each do |key|
31
+ define_method :"#{key}=" do |value|
17
32
  set_state({key.to_sym => value})
18
- instance_variable_set("@#{key}".to_sym, value)
33
+ instance_variable_set(:"@#{key}", value)
19
34
  end
20
35
  end
21
36
 
22
37
  def set_xy(x, y)
23
- set_state({:xy => [x, y]})
38
+ set_state({xy: [x, y]})
24
39
  @x, @y = x, y
25
40
  end
41
+
42
+ def hex
43
+ ColorConversion::Color.new(h: hue, s: saturation, b: brightness).hex
44
+ end
45
+
46
+ def hex=(hex)
47
+ hex = "##{hex}" unless hex.start_with?("#")
48
+ hsb = ColorConversion::Color.new(hex).hsb
49
+
50
+ # Map values from standard HSB to what Hue wants and update state
51
+ state = {
52
+ hue: ((hsb[:h].to_f / 360.0) * HUE_RANGE.last.to_f).to_i,
53
+ saturation: ((hsb[:s].to_f / 100.0) * SATURATION_RANGE.last.to_f).to_i,
54
+ brightness: ((hsb[:b].to_f / 100.0) * BRIGHTNESS_RANGE.last.to_f).to_i
55
+ }
56
+
57
+ set_state(state)
58
+
59
+ @hue = state[:hue]
60
+ @saturation = state[:saturation]
61
+ @brightness = state[:brightness]
62
+ end
26
63
  end
27
64
  end
data/lib/hue/errors.rb CHANGED
@@ -2,33 +2,47 @@ module Hue
2
2
  class Error < StandardError; end
3
3
 
4
4
  class UnauthorizedUser < Error; end
5
+
5
6
  class InvalidJSON < Error; end
7
+
6
8
  class ResourceNotAvailable < Error; end
9
+
7
10
  class MethodNotAvailable < Error; end
11
+
8
12
  class MissingBody < Error; end
13
+
9
14
  class ParameterNotAvailable < Error; end
15
+
10
16
  class InvalidValueForParameter < Error; end
17
+
11
18
  class ParameterNotModifiable < Error; end
19
+
12
20
  class InternalError < Error; end
21
+
13
22
  class LinkButtonNotPressed < Error; end
23
+
14
24
  class ParameterNotModifiableWhileOff < ParameterNotModifiable; end
25
+
15
26
  class TooManyGroups < Error; end
27
+
16
28
  class GroupTooFull < Error; end
17
29
 
18
30
  class InvalidUsername < Error; end
31
+
19
32
  class UnknownError < Error; end
33
+
20
34
  class NoBridgeFound < Error; end
21
35
 
22
36
  # Status code to exception map
23
37
  ERROR_MAP = {
24
- 1 => Hue::UnauthorizedUser,
25
- 2 => Hue::InvalidJSON,
26
- 3 => Hue::ResourceNotAvailable,
27
- 4 => Hue::MethodNotAvailable,
28
- 5 => Hue::MissingBody,
29
- 6 => Hue::ParameterNotAvailable,
30
- 7 => Hue::InvalidValueForParameter,
31
- 8 => Hue::ParameterNotModifiable,
38
+ 1 => Hue::UnauthorizedUser,
39
+ 2 => Hue::InvalidJSON,
40
+ 3 => Hue::ResourceNotAvailable,
41
+ 4 => Hue::MethodNotAvailable,
42
+ 5 => Hue::MissingBody,
43
+ 6 => Hue::ParameterNotAvailable,
44
+ 7 => Hue::InvalidValueForParameter,
45
+ 8 => Hue::ParameterNotModifiable,
32
46
  901 => Hue::InternalError,
33
47
  101 => Hue::LinkButtonNotPressed,
34
48
  201 => Hue::ParameterNotModifiableWhileOff,
data/lib/hue/group.rb CHANGED
@@ -11,19 +11,19 @@ module Hue
11
11
  attr_reader :bridge
12
12
 
13
13
  # A unique, editable name given to the group.
14
- attr_accessor :name
14
+ attr_reader :name
15
15
 
16
16
  # Hue of the group. This is a wrapping value between 0 and 65535.
17
17
  # Both 0 and 65535 are red, 25500 is green and 46920 is blue.
18
18
  attr_accessor :hue
19
19
 
20
- # Saturation of the group. 255 is the most saturated (colored)
20
+ # Saturation of the group. 254 is the most saturated (colored)
21
21
  # and 0 is the least saturated (white).
22
22
  attr_accessor :saturation
23
23
 
24
24
  # Brightness of the group. This is a scale from the minimum
25
25
  # brightness the group is capable of, 0, to the maximum capable
26
- # brightness, 255. Note a brightness of 0 is not off.
26
+ # brightness, 254. Note a brightness of 0 is not off.
27
27
  attr_accessor :brightness
28
28
 
29
29
  # The x coordinate of a color in CIE color space. Between 0 and 1.
@@ -58,16 +58,14 @@ module Hue
58
58
  end
59
59
 
60
60
  def lights
61
- @lights ||= begin
62
- @light_ids.map do |light_id|
63
- @client.light(light_id)
64
- end
61
+ @lights ||= @light_ids.map do |light_id|
62
+ @client.light(light_id)
65
63
  end
66
64
  end
67
65
 
68
66
  def name=(name)
69
- resp = set_group_state({:name => name})
70
- @name = new? ? name : resp[0]['success']["/groups/#{id}/name"]
67
+ resp = set_group_state({name: name})
68
+ @name = new? ? name : resp[0]["success"]["/groups/#{id}/name"]
71
69
  end
72
70
 
73
71
  def lights=(light_ids)
@@ -78,17 +76,17 @@ module Hue
78
76
  @light_ids = light_ids.uniq
79
77
  @lights = nil # resets the memoization
80
78
 
81
- set_group_state({:lights => @light_ids})
79
+ set_group_state({lights: @light_ids})
82
80
  end
83
81
 
84
82
  def scene=(scene)
85
83
  scene_id = scene.is_a?(Scene) ? scene.id : scene
86
- set_group_state({:scene => scene_id})
84
+ set_group_state({scene: scene_id})
87
85
  end
88
86
 
89
87
  def <<(light_id)
90
88
  @light_ids << light_id
91
- set_group_state({:lights => @light_ids})
89
+ set_group_state({lights: @light_ids})
92
90
  end
93
91
  alias_method :add_light, :<<
94
92
 
@@ -120,8 +118,8 @@ module Hue
120
118
 
121
119
  def create!
122
120
  body = {
123
- :name => @name,
124
- :lights => @light_ids,
121
+ name: @name,
122
+ lights: @light_ids
125
123
  }
126
124
 
127
125
  uri = URI.parse("http://#{@bridge.ip}/api/#{@client.username}/groups")
@@ -129,7 +127,7 @@ module Hue
129
127
  response = http.request_post(uri.path, JSON.dump(body))
130
128
  json = JSON(response.body)
131
129
 
132
- @id = json[0]['success']['id']
130
+ @id = json[0]["success"]["id"]
133
131
  end
134
132
 
135
133
  def destroy!
@@ -137,7 +135,7 @@ module Hue
137
135
  http = Net::HTTP.new(uri.host)
138
136
  response = http.delete(uri.path)
139
137
  json = JSON(response.body)
140
- @id = nil if json[0]['success']
138
+ @id = nil if json[0]["success"]
141
139
  end
142
140
 
143
141
  def new?
@@ -147,22 +145,22 @@ module Hue
147
145
  private
148
146
 
149
147
  GROUP_KEYS_MAP = {
150
- :name => :name,
151
- :light_ids => :lights,
152
- :type => :type,
153
- :state => :action
148
+ name: :name,
149
+ light_ids: :lights,
150
+ type: :type,
151
+ state: :action
154
152
  }
155
153
 
156
154
  STATE_KEYS_MAP = {
157
- :on => :on,
158
- :brightness => :bri,
159
- :hue => :hue,
160
- :saturation => :sat,
161
- :xy => :xy,
162
- :color_temperature => :ct,
163
- :alert => :alert,
164
- :effect => :effect,
165
- :color_mode => :colormode,
155
+ on: :on,
156
+ brightness: :bri,
157
+ hue: :hue,
158
+ saturation: :sat,
159
+ xy: :xy,
160
+ color_temperature: :ct,
161
+ alert: :alert,
162
+ effect: :effect,
163
+ color_mode: :colormode
166
164
  }
167
165
 
168
166
  def unpack(data)
@@ -170,7 +168,7 @@ module Hue
170
168
 
171
169
  unless new?
172
170
  unpack_hash(@state, STATE_KEYS_MAP)
173
- @x, @y = @state['xy']
171
+ @x, @y = @state["xy"]
174
172
  end
175
173
  end
176
174
 
data/lib/hue/light.rb CHANGED
@@ -3,9 +3,6 @@ module Hue
3
3
  include TranslateKeys
4
4
  include EditableState
5
5
 
6
- HUE_RANGE = 0..65535
7
- SATURATION_RANGE = 0..255
8
- BRIGHTNESS_RANGE = 0..255
9
6
  COLOR_TEMPERATURE_RANGE = 153..500
10
7
 
11
8
  # Unique identification number.
@@ -15,19 +12,19 @@ module Hue
15
12
  attr_reader :bridge
16
13
 
17
14
  # A unique, editable name given to the light.
18
- attr_accessor :name
15
+ attr_reader :name
19
16
 
20
17
  # Hue of the light. This is a wrapping value between 0 and 65535.
21
18
  # Both 0 and 65535 are red, 25500 is green and 46920 is blue.
22
19
  attr_reader :hue
23
20
 
24
- # Saturation of the light. 255 is the most saturated (colored)
21
+ # Saturation of the light. 254 is the most saturated (colored)
25
22
  # and 0 is the least saturated (white).
26
23
  attr_reader :saturation
27
24
 
28
25
  # Brightness of the light. This is a scale from the minimum
29
26
  # brightness the light is capable of, 0, to the maximum capable
30
- # brightness, 255. Note a brightness of 0 is not off.
27
+ # brightness, 254. Note a brightness of 0 is not off.
31
28
  attr_reader :brightness
32
29
 
33
30
  # The x coordinate of a color in CIE color space. Between 0 and 1.
@@ -84,6 +81,15 @@ module Hue
84
81
  # Reserved for future functionality.
85
82
  attr_reader :point_symbol
86
83
 
84
+ # The unique ID of the light.
85
+ attr_reader :uid
86
+
87
+ # The hash of capabilities of the light
88
+ attr_reader :capabilities
89
+
90
+ # The config hash
91
+ attr_reader :config
92
+
87
93
  def initialize(client, bridge, id, hash)
88
94
  @client = client
89
95
  @bridge = bridge
@@ -92,21 +98,21 @@ module Hue
92
98
  end
93
99
 
94
100
  def name=(new_name)
95
- unless (1..32).include?(new_name.length)
96
- raise InvalidValueForParameter, 'name must be between 1 and 32 characters.'
101
+ unless (1..32).cover?(new_name.length)
102
+ raise InvalidValueForParameter, "name must be between 1 and 32 characters."
97
103
  end
98
104
 
99
105
  body = {
100
- :name => new_name
106
+ name: new_name
101
107
  }
102
108
 
103
109
  uri = URI.parse(base_url)
104
110
  http = Net::HTTP.new(uri.host)
105
111
  response = http.request_put(uri.path, JSON.dump(body))
106
112
  response = JSON(response.body).first
107
- if response['success']
113
+ if response["success"]
108
114
  @name = new_name
109
- # else
115
+ # else
110
116
  # TODO: Error
111
117
  end
112
118
  end
@@ -115,7 +121,7 @@ module Hue
115
121
  # always returns true, functionality will be added in a future
116
122
  # patch.
117
123
  def reachable?
118
- @state['reachable']
124
+ @state["reachable"]
119
125
  end
120
126
 
121
127
  # @param transition The duration of the transition from the light’s current
@@ -126,7 +132,7 @@ module Hue
126
132
  body = translate_keys(attributes, STATE_KEYS_MAP)
127
133
 
128
134
  # Add transition
129
- body.merge!({:transitiontime => transition}) if transition
135
+ body[:transitiontime] = transition if transition
130
136
 
131
137
  uri = URI.parse("#{base_url}/state")
132
138
  http = Net::HTTP.new(uri.host)
@@ -140,34 +146,37 @@ module Hue
140
146
  unpack(json)
141
147
  end
142
148
 
143
- private
149
+ private
144
150
 
145
151
  KEYS_MAP = {
146
- :state => :state,
147
- :type => :type,
148
- :name => :name,
149
- :model => :modelid,
150
- :software_version => :swversion,
151
- :point_symbol => :pointsymbol
152
+ state: :state,
153
+ type: :type,
154
+ name: :name,
155
+ model: :modelid,
156
+ software_version: :swversion,
157
+ point_symbol: :pointsymbol,
158
+ uid: :uniqueid,
159
+ capabilities: :capabilities,
160
+ config: :config
152
161
  }
153
162
 
154
163
  STATE_KEYS_MAP = {
155
- :on => :on,
156
- :brightness => :bri,
157
- :hue => :hue,
158
- :saturation => :sat,
159
- :xy => :xy,
160
- :color_temperature => :ct,
161
- :alert => :alert,
162
- :effect => :effect,
163
- :color_mode => :colormode,
164
- :reachable => :reachable,
164
+ on: :on,
165
+ brightness: :bri,
166
+ hue: :hue,
167
+ saturation: :sat,
168
+ xy: :xy,
169
+ color_temperature: :ct,
170
+ alert: :alert,
171
+ effect: :effect,
172
+ color_mode: :colormode,
173
+ reachable: :reachable
165
174
  }
166
175
 
167
176
  def unpack(hash)
168
177
  unpack_hash(hash, KEYS_MAP)
169
178
  unpack_hash(@state, STATE_KEYS_MAP)
170
- @x, @y = @state['xy']
179
+ @x, @y = @state["xy"]
171
180
  end
172
181
 
173
182
  def base_url
data/lib/hue/scene.rb CHANGED
@@ -24,19 +24,17 @@ module Hue
24
24
  end
25
25
 
26
26
  def lights
27
- @lights ||= begin
28
- @light_ids.map do |light_id|
29
- @client.light(light_id)
30
- end
27
+ @lights ||= @light_ids.map do |light_id|
28
+ @client.light(light_id)
31
29
  end
32
30
  end
33
31
 
34
32
  private
35
33
 
36
34
  SCENE_KEYS_MAP = {
37
- :name => :name,
38
- :light_ids => :lights,
39
- :active => :active,
35
+ name: :name,
36
+ light_ids: :lights,
37
+ active: :active
40
38
  }
41
39
 
42
40
  def unpack(data)
@@ -14,7 +14,7 @@ module Hue
14
14
  map.each do |local_key, remote_key|
15
15
  value = hash[remote_key.to_s]
16
16
  next unless value
17
- instance_variable_set("@#{local_key}", value)
17
+ instance_variable_set(:"@#{local_key}", value)
18
18
  end
19
19
  end
20
20
  end
data/lib/hue/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Hue
2
- VERSION = '0.3.0'
2
+ VERSION = "0.3.1"
3
3
  end
data/lib/hue.rb CHANGED
@@ -1,12 +1,12 @@
1
- require 'hue/version'
2
- require 'hue/errors'
3
- require 'hue/client'
4
- require 'hue/bridge'
5
- require 'hue/editable_state'
6
- require 'hue/translate_keys'
7
- require 'hue/light'
8
- require 'hue/group'
9
- require 'hue/scene'
1
+ require "hue/version"
2
+ require "hue/errors"
3
+ require "hue/client"
4
+ require "hue/bridge"
5
+ require "hue/editable_state"
6
+ require "hue/translate_keys"
7
+ require "hue/light"
8
+ require "hue/group"
9
+ require "hue/scene"
10
10
 
11
11
  module Hue
12
12
  USERNAME_RANGE = 10..40
@@ -1,25 +1,26 @@
1
- require 'test_helper'
1
+ require "test_helper"
2
2
 
3
3
  class ClientTest < Minitest::Test
4
4
  def before_setup
5
5
  super
6
6
 
7
- stub_request(:get, "https://discovery.meethue.com/").
8
- to_return(:body => '[{"id":"ffa57b3b257200065704","internalipaddress":"192.168.0.1"},{"id":"63c2fc01391276a319f9","internalipaddress":"192.168.0.2"}]')
7
+ stub_request(:get, "https://discovery.meethue.com/")
8
+ .to_return(body: '[{"id":"ffa57b3b257200065704","internalipaddress":"192.168.0.1"},{"id":"63c2fc01391276a319f9","internalipaddress":"192.168.0.2"}]')
9
9
 
10
- stub_request(:get, %r{http://192.168.0.1/api/*}).to_return(:body => '[{"success":true}]')
11
- stub_request(:get, %r{http://192.168.0.2/api/*}).to_return(:body => '[{"success":true}]')
10
+ stub_request(:get, %r{http://192.168.0.1/api}).to_return(body: '[{"success":true}]')
11
+ stub_request(:get, %r{http://192.168.0.1/api/*}).to_return(body: '[{"success":true}]')
12
+ stub_request(:get, %r{http://192.168.0.2/api/*}).to_return(body: '[{"success":true}]')
12
13
  end
13
14
 
14
15
  def test_with_bridge_id
15
16
  client = Hue::Client.new(use_mdns: false)
16
- client.stub :find_bridge_id, '63c2fc01391276a319f9' do
17
- assert_equal '63c2fc01391276a319f9', client.bridge.id
17
+ client.stub :find_bridge_id, "63c2fc01391276a319f9" do
18
+ assert_equal "63c2fc01391276a319f9", client.bridge.id
18
19
  end
19
20
  end
20
21
 
21
22
  def test_without_bridge_id
22
23
  client = Hue::Client.new(use_mdns: false)
23
- assert_equal 'ffa57b3b257200065704', client.bridge.id
24
+ assert_equal "ffa57b3b257200065704", client.bridge.id
24
25
  end
25
26
  end
@@ -1,24 +1,44 @@
1
- require 'test_helper'
1
+ require "test_helper"
2
2
 
3
3
  class LightTest < Minitest::Test
4
4
  def before_setup
5
5
  super
6
6
 
7
- stub_request(:get, "https://discovery.meethue.com/").
8
- to_return(:body => '[{"internalipaddress":"localhost"}]')
7
+ stub_request(:get, "https://discovery.meethue.com/")
8
+ .to_return(body: '[{"internalipaddress":"localhost"}]')
9
9
 
10
- stub_request(:get, %r{http://localhost/api/*}).to_return(:body => '[{"success":true}]')
11
- stub_request(:post, 'http://localhost/api').to_return(:body => '[{"success":{"username":"ruby"}}]')
12
- stub_request(:put, %r{http://localhost/api*}).to_return(:body => '[{}]')
10
+ stub_request(:get, %r{http://localhost/api/*}).to_return(body: '[{"success":true}]')
11
+ stub_request(:post, "http://localhost/api").to_return(body: '[{"success":{"username":"ruby"}}]')
12
+ stub_request(:put, %r{http://localhost/api*}).to_return(body: "[{}]")
13
13
  end
14
14
 
15
- %w{on hue saturation brightness color_temperature alert effect}.each do |attribute|
16
- define_method "test_setting_#{attribute}" do
15
+ %w[on hue saturation brightness color_temperature alert effect].each do |attribute|
16
+ define_method :"test_setting_#{attribute}" do
17
17
  client = Hue::Client.new(use_mdns: false)
18
18
  light = Hue::Light.new(client, client.bridge, 0, {"state" => {}})
19
19
 
20
- light.send("#{attribute}=", 24)
20
+ light.send(:"#{attribute}=", 24)
21
21
  assert_requested :put, %r{http://localhost/api/.*/lights/0}
22
22
  end
23
23
  end
24
+
25
+ def test_toggle_while_off
26
+ client = Hue::Client.new(use_mdns: false)
27
+ light = Hue::Light.new(client, client.bridge, 0, {"state" => {}})
28
+ assert_equal false, light.on?
29
+
30
+ light.toggle!
31
+ assert_requested :put, %r{http://localhost/api/.*/lights/0}
32
+ assert_equal true, light.on?
33
+ end
34
+
35
+ def test_toggle_while_on
36
+ client = Hue::Client.new(use_mdns: false)
37
+ light = Hue::Light.new(client, client.bridge, 0, {"state" => {"on" => true}})
38
+ assert_equal true, light.on?
39
+
40
+ light.toggle!
41
+ assert_requested :put, %r{http://localhost/api/.*/lights/0}
42
+ assert_equal false, light.on?
43
+ end
24
44
  end
data/test/test_helper.rb CHANGED
@@ -1,6 +1,6 @@
1
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
- require 'hue'
1
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
2
+ require "hue"
3
3
 
4
- require 'minitest'
5
- require 'webmock/minitest'
6
- require 'minitest/autorun'
4
+ require "minitest"
5
+ require "webmock/minitest"
6
+ require "minitest/autorun"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Soffes
@@ -39,21 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: log_switch
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - '='
46
- - !ruby/object:Gem::Version
47
- version: 0.4.0
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - '='
53
- - !ruby/object:Gem::Version
54
- version: 0.4.0
55
- - !ruby/object:Gem::Dependency
56
- name: curb
42
+ name: color_conversion
57
43
  requirement: !ruby/object:Gem::Requirement
58
44
  requirements:
59
45
  - - ">="
@@ -66,48 +52,23 @@ dependencies:
66
52
  - - ">="
67
53
  - !ruby/object:Gem::Version
68
54
  version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: minitest
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '5.0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '5.0'
83
- - !ruby/object:Gem::Dependency
84
- name: webmock
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
55
  description: Work with Philips Hue light bulbs.
98
56
  email:
99
57
  - sam@soff.es
100
58
  executables:
59
+ - console
101
60
  - hue
102
61
  extensions: []
103
62
  extra_rdoc_files: []
104
63
  files:
105
64
  - ".github/workflows/main.yml"
106
65
  - ".gitignore"
66
+ - ".ruby-version"
107
67
  - Gemfile
108
68
  - LICENSE
109
69
  - README.md
110
70
  - Rakefile
71
+ - bin/console
111
72
  - bin/hue
112
73
  - hue.gemspec
113
74
  - lib/hue.rb
@@ -147,7 +108,4 @@ rubygems_version: 3.4.22
147
108
  signing_key:
148
109
  specification_version: 4
149
110
  summary: Work with Philips Hue light bulbs from Ruby.
150
- test_files:
151
- - test/hue/client_test.rb
152
- - test/hue/light_test.rb
153
- - test/test_helper.rb
111
+ test_files: []