hue 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af74df93c5514679bab0613c9c6c87b0a0dfae19b919fc903ad42a8fafe9b681
4
- data.tar.gz: 0afb9bd5b7ee11be0a1dce6b56846c6d13fa7cd9a9b67e2f9c8014c8d03f0fb7
3
+ metadata.gz: a93b5e3363bf3af0a578de606c2d061c44db405f77ec3d88dacbbae9ac01b420
4
+ data.tar.gz: 3e5e17cd8438264c403ffab5292d813c08ab9ccff39e4a3b680fe912e56fab3d
5
5
  SHA512:
6
- metadata.gz: 00f64a5fdad18722af090747e6a2dfe2a5fefb556bcd634ee7b498f54df80e23e94975c295a2925a46cf2166e88df0af07dee1999e26446f7e42e66ebbc8778b
7
- data.tar.gz: f54f5552bceb7456b0a1d6ccdc29f7ca3cb01636231d83a5f0d7d93b907defce6bfbfcb0e2f96444e49543fbb85f7cda66586f72eedaea912c7a18f5ededb570
6
+ metadata.gz: 05103d25ba76ff79bfbf7655009d818a4425fc0d20dce2146473fe1c93b8d99dcaabe8ebaeed90e8bab88d75ed7679667941ae40d3c1eb181a2f0e39f0869e84
7
+ data.tar.gz: ca26e94b2d5ed62af06038da96a832f9694bc1b09065bdd161be6c222bd4c872397114b7565a89e4669d02cc2c7925907cdae6cb84db67d077fb9d638e7c27a5
@@ -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@v6
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@v6
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.4.7
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/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013-2024 Sam Soffes, https://soff.es
1
+ Copyright (c) 2013-2025 Sam Soffes, https://soff.es
2
2
 
3
3
  MIT License
4
4
 
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
@@ -73,8 +73,10 @@ module Hue
73
73
 
74
74
  def lights
75
75
  @lights ||= begin
76
- json = JSON(Net::HTTP.get(URI.parse(base_url)))
77
- json['lights'].map do |key, value|
76
+ uri = URI.parse(base_url)
77
+ http = HttpClient.create(uri)
78
+ json = JSON(http.get(uri.path).body)
79
+ json["lights"].map do |key, value|
78
80
  Light.new(@client, self, key, value)
79
81
  end
80
82
  end
@@ -82,14 +84,16 @@ module Hue
82
84
 
83
85
  def add_lights
84
86
  uri = URI.parse("#{base_url}/lights")
85
- http = Net::HTTP.new(uri.host)
87
+ http = HttpClient.create(uri)
86
88
  response = http.request_post(uri.path, nil)
87
- (response.body).first
89
+ response.body.first
88
90
  end
89
91
 
90
92
  def groups
91
93
  @groups ||= begin
92
- json = JSON(Net::HTTP.get(URI.parse("#{base_url}/groups")))
94
+ uri = URI.parse("#{base_url}/groups")
95
+ http = HttpClient.create(uri)
96
+ json = JSON(http.get(uri.path).body)
93
97
  json.map do |id, data|
94
98
  Group.new(@client, self, id, data)
95
99
  end
@@ -98,43 +102,47 @@ module Hue
98
102
 
99
103
  def scenes
100
104
  @scenes ||= begin
101
- json = JSON(Net::HTTP.get(URI.parse("#{base_url}/scenes")))
105
+ uri = URI.parse("#{base_url}/scenes")
106
+ http = HttpClient.create(uri)
107
+ json = JSON(http.get(uri.path).body)
102
108
  json.map do |id, data|
103
109
  Scene.new(@client, self, id, data)
104
110
  end
105
111
  end
106
112
  end
107
113
 
108
- private
114
+ private
109
115
 
110
116
  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,
117
+ id: :id,
118
+ ip: :internalipaddress,
119
+ name: :name,
120
+ proxy_port: :proxyport,
121
+ software_update: :swupdate,
122
+ ip_whitelist: :whitelist,
123
+ software_version: :swversion,
124
+ proxy_address: :proxyaddress,
125
+ mac_address: :macaddress,
126
+ network_mask: :netmask,
127
+ portal_services: :portalservices
122
128
  }
123
129
 
124
130
  def unpack(hash)
125
131
  KEYS_MAP.each do |local_key, remote_key|
126
132
  value = hash[remote_key.to_s]
127
133
  next unless value
128
- instance_variable_set("@#{local_key}", value)
134
+ instance_variable_set(:"@#{local_key}", value)
129
135
  end
130
136
  end
131
137
 
132
138
  def get_configuration
133
- JSON(Net::HTTP.get(URI.parse("#{base_url}/config")))
139
+ uri = URI.parse("#{base_url}/config")
140
+ http = HttpClient.create(uri)
141
+ JSON(http.get(uri.path).body)
134
142
  end
135
143
 
136
144
  def base_url
137
- "http://#{ip}/api/#{@client.username}"
145
+ "https://#{ip}/api/#{@client.username}"
138
146
  end
139
147
  end
140
148
  end
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,7 @@
1
- require 'net/http'
2
- require 'json'
3
- require 'resolv'
4
- require 'curb'
1
+ require "net/http"
2
+ require "openssl"
3
+ require "json"
4
+ require "resolv"
5
5
 
6
6
  module Hue
7
7
  class Client
@@ -24,11 +24,11 @@ module Hue
24
24
  end
25
25
 
26
26
  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
27
+ @bridge_id ||= find_bridge_id
28
+ bridge = if @bridge_id
29
+ bridges.find { |b| b.id == @bridge_id }
30
30
  else
31
- bridge = bridges.first
31
+ bridges.first
32
32
  end
33
33
  raise NoBridgeFound unless bridge
34
34
  bridge
@@ -53,7 +53,7 @@ module Hue
53
53
 
54
54
  def light(id)
55
55
  id = id.to_s
56
- lights.select { |l| l.id == id }.first
56
+ lights.find { |l| l.id == id }
57
57
  end
58
58
 
59
59
  def groups
@@ -64,7 +64,7 @@ module Hue
64
64
  return Group.new(self, bridge) if id.nil?
65
65
 
66
66
  id = id.to_s
67
- groups.select { |g| g.id == id }.first
67
+ groups.find { |g| g.id == id }
68
68
  end
69
69
 
70
70
  def scenes
@@ -73,59 +73,61 @@ module Hue
73
73
 
74
74
  def scene(id)
75
75
  id = id.to_s
76
- scenes.select { |s| s.id == id }.first
76
+ scenes.find { |s| s.id == id }
77
77
  end
78
78
 
79
79
  private
80
80
 
81
81
  def find_username
82
- return ENV['HUE_USERNAME'] if ENV['HUE_USERNAME']
82
+ return ENV["HUE_USERNAME"] if ENV["HUE_USERNAME"]
83
83
 
84
- json = JSON(File.read(File.expand_path('~/.hue')))
85
- json['username']
84
+ json = JSON(File.read(File.expand_path("~/.hue")))
85
+ json["username"]
86
86
  rescue
87
- return nil
87
+ nil
88
88
  end
89
89
 
90
90
  def validate_user
91
- response = JSON(Net::HTTP.get(URI.parse("http://#{bridge.ip}/api/#{@username}")))
91
+ uri = URI.parse("https://#{bridge.ip}/api/#{@username}")
92
+ http = HttpClient.create(uri)
93
+ response = JSON(http.get(uri.path).body)
92
94
 
93
95
  if response.is_a? Array
94
96
  response = response.first
95
97
  end
96
98
 
97
- if error = response['error']
99
+ if (error = response["error"])
98
100
  raise get_error(error)
99
101
  end
100
102
 
101
- response['success']
103
+ response["success"]
102
104
  end
103
105
 
104
106
  def register_user
105
107
  body = JSON.dump({
106
- devicetype: 'Ruby'
108
+ devicetype: "Ruby"
107
109
  })
108
110
 
109
- uri = URI.parse("http://#{bridge.ip}/api")
110
- http = Net::HTTP.new(uri.host)
111
+ uri = URI.parse("https://#{bridge.ip}/api")
112
+ http = HttpClient.create(uri)
111
113
  response = JSON(http.request_post(uri.path, body).body).first
112
114
 
113
- if error = response['error']
115
+ if (error = response["error"])
114
116
  raise get_error(error)
115
117
  end
116
118
 
117
- if @username = response['success']['username']
118
- File.write(File.expand_path('~/.hue'), JSON.dump({username: @username}))
119
+ if (@username = response["success"]["username"])
120
+ File.write(File.expand_path("~/.hue"), JSON.dump({username: @username}))
119
121
  end
120
122
  end
121
123
 
122
124
  def find_bridge_id
123
- return ENV['HUE_BRIDGE_ID'] if ENV['HUE_BRIDGE_ID']
125
+ return ENV["HUE_BRIDGE_ID"] if ENV["HUE_BRIDGE_ID"]
124
126
 
125
- json = JSON(File.read(File.expand_path('~/.hue')))
126
- json['bridge_id']
127
+ json = JSON(File.read(File.expand_path("~/.hue")))
128
+ json["bridge_id"]
127
129
  rescue
128
- return nil
130
+ nil
129
131
  end
130
132
 
131
133
  def discovery_mdns(bs)
@@ -136,8 +138,8 @@ module Hue
136
138
  bridge_target = resolver.getresource(bridge_ptr.name, Resolv::DNS::Resource::IN::SRV).target
137
139
 
138
140
  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
141
+ "id" => resolver.getresource(bridge_ptr.name, Resolv::DNS::Resource::IN::TXT).strings[0].split("=")[1],
142
+ "internalipaddress" => resolver.getresource(bridge_target, Resolv::DNS::Resource::IN::A).address
141
143
  }
142
144
 
143
145
  bs << Bridge.new(self, bridge_hash)
@@ -145,20 +147,18 @@ module Hue
145
147
  end
146
148
 
147
149
  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|
150
+ uri = URI("https://discovery.meethue.com/")
151
+ response = Net::HTTP.get(uri)
152
+
153
+ JSON(response).each do |hash|
154
154
  bs << Bridge.new(self, hash)
155
155
  end
156
156
  end
157
157
 
158
158
  def get_error(error)
159
159
  # Find error class and return instance
160
- klass = Hue::ERROR_MAP[error['type']] || UnknownError unless klass
161
- klass.new(error['description'])
160
+ klass ||= Hue::ERROR_MAP[error["type"]] || UnknownError
161
+ klass.new(error["description"])
162
162
  end
163
163
  end
164
164
  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