winker 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +169 -0
- data/Rakefile +2 -0
- data/lib/winker/api_methods.rb +86 -0
- data/lib/winker/connection.rb +39 -0
- data/lib/winker/device.rb +57 -0
- data/lib/winker/devices/device_methods.rb +42 -0
- data/lib/winker/devices/generic_device.rb +14 -0
- data/lib/winker/devices/hub.rb +10 -0
- data/lib/winker/devices/light_bulb.rb +37 -0
- data/lib/winker/devices/on_off.rb +37 -0
- data/lib/winker/devices/sensor_pod.rb +19 -0
- data/lib/winker/devices/unknown_device.rb +9 -0
- data/lib/winker/float.rb +9 -0
- data/lib/winker/group.rb +51 -0
- data/lib/winker/scene.rb +45 -0
- data/lib/winker/temperature.rb +39 -0
- data/lib/winker/version.rb +3 -0
- data/lib/winker.rb +51 -0
- data/winker.gemspec +29 -0
- metadata +180 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6822f9ff1ac2caebfef3e784c0a336fe8a9685bc
|
4
|
+
data.tar.gz: b5a370c52f88f6f953355173f76805a6d3e4ae59
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e0e17eb42a6804a6a7a814e1252bdc9510aa057619361f9d77321bfa9d6152a88cca634a78cf71d8f3161f4843ac583b4b95126887f6ce92c4786a89477cb002
|
7
|
+
data.tar.gz: 0710e4bcb3df3d731deb1634371eb05d5b1975a36946f82dd936aeb50176fbc9242b4dacc75ebd0d112d10959cd919a06e9468ca1a47da4572f3728040fb75b7
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Kelly Mahan
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
# Winker
|
2
|
+
|
3
|
+
Winker is a gem written to support the wink api and any other associated platforms.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'winker'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install winker
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
|
24
|
+
Winker.configure do |wink|
|
25
|
+
wink.client_id = "******************"
|
26
|
+
wink.client_secret = "******************"
|
27
|
+
wink.access_token = nil
|
28
|
+
wink.refresh_token = nil
|
29
|
+
wink.username = "email@domain.com"
|
30
|
+
wink.password = "**********"
|
31
|
+
wink.endpoint = "https://winkapi.quirky.com"
|
32
|
+
end
|
33
|
+
|
34
|
+
#retrieve the access_token and refresh_token
|
35
|
+
Winker.authorize
|
36
|
+
|
37
|
+
#get a list of devices, the hub always seems to be the first device
|
38
|
+
devices = Winker.devices
|
39
|
+
|
40
|
+
devices.count
|
41
|
+
=> 8
|
42
|
+
|
43
|
+
devices[1].name
|
44
|
+
=> "Front porch 1"
|
45
|
+
|
46
|
+
|
47
|
+
#Device Methods/Attributes
|
48
|
+
Some status methods are blocking in the sense that if a status change is sent, such as powering the device on or off, the next time you call powered? it will refresh every 2 seconds until last updated at time is greater than when the status change was called. If 20 seconds pass before an update then the it throws and error that it hasn't received an update. During my testing an update normally took about 4 seconds. But at times would take much longer.
|
49
|
+
|
50
|
+
examples
|
51
|
+
|
52
|
+
devices = Winker.devices #returns an array of device objects
|
53
|
+
devices[1].type
|
54
|
+
=> "light_bulb"
|
55
|
+
|
56
|
+
Each device has it's own associated type. To make things easier when devices are loaded methods are included to help interact with the device so update(options) doesn't have to be called for every interaction.
|
57
|
+
|
58
|
+
##Generic
|
59
|
+
|
60
|
+
refresh
|
61
|
+
#This queries the api to update the device status.
|
62
|
+
#normally device status is cached unless a status update is called on the device
|
63
|
+
#the next time a device status is called a refresh is called first.
|
64
|
+
|
65
|
+
update(options)
|
66
|
+
#options is a hash with the requested update information
|
67
|
+
#all devices make use of this method
|
68
|
+
#example for powering on a device
|
69
|
+
#update(desired_state: {powered: "true"})
|
70
|
+
#for changing a device name
|
71
|
+
#update(name: "New Device name")
|
72
|
+
#check the api for all updatable information.
|
73
|
+
|
74
|
+
type
|
75
|
+
#returns the type of device
|
76
|
+
|
77
|
+
id
|
78
|
+
#returns the id of the device. Used for making api calls for the device
|
79
|
+
|
80
|
+
updated_at
|
81
|
+
#last time there was an update for the device. Used to tell when a status update has succeeded
|
82
|
+
|
83
|
+
#method_missing is also used to access the json data directly from the device query
|
84
|
+
#with this you can get other information about the device. Not all devices have the same attributes
|
85
|
+
#example attributes:
|
86
|
+
|
87
|
+
name
|
88
|
+
manufacturer_device_model
|
89
|
+
manufacturer_device_id
|
90
|
+
device_manufacturer
|
91
|
+
model_name
|
92
|
+
radio_type
|
93
|
+
last_reading
|
94
|
+
....
|
95
|
+
|
96
|
+
|
97
|
+
##OnOff < Generic
|
98
|
+
on
|
99
|
+
#turns a device on, brightness level is preserved
|
100
|
+
|
101
|
+
off
|
102
|
+
#turns a device off, brightness level is preserved
|
103
|
+
|
104
|
+
powered?
|
105
|
+
#checks the powered status of the device, *blocking method
|
106
|
+
|
107
|
+
on?
|
108
|
+
#alias for powered?
|
109
|
+
|
110
|
+
off?
|
111
|
+
#!powered?
|
112
|
+
|
113
|
+
##LightBulb < OnOff
|
114
|
+
brightness
|
115
|
+
#returns the last brightness level. 0.01 < brightness <= 1
|
116
|
+
#even when the device is powered off the last brightness level is returned
|
117
|
+
#*blocking method
|
118
|
+
|
119
|
+
brightness=
|
120
|
+
#sets the brightness level and powers on the device if off
|
121
|
+
|
122
|
+
##Sensor Pod < Generic
|
123
|
+
temp
|
124
|
+
#returns the current temperature in celcius
|
125
|
+
#TODO return a temp object that defaults to chosen temp scale
|
126
|
+
|
127
|
+
humidity
|
128
|
+
#returns the current humidity
|
129
|
+
|
130
|
+
#Group Methods
|
131
|
+
on
|
132
|
+
#turns all devices in the group on
|
133
|
+
|
134
|
+
off
|
135
|
+
#turns all devices in the group off
|
136
|
+
|
137
|
+
brightness=
|
138
|
+
#sets the brightness level for all devices in the group.
|
139
|
+
#I believe a non dimmable device is simply turned on and brightness is ignored.
|
140
|
+
|
141
|
+
members
|
142
|
+
#returns an array of all devices include in the group.
|
143
|
+
|
144
|
+
#method_missing is also included to retrieve some attributes
|
145
|
+
name
|
146
|
+
order
|
147
|
+
|
148
|
+
#Scene Methods
|
149
|
+
activate
|
150
|
+
#triggers the scene
|
151
|
+
|
152
|
+
members
|
153
|
+
#returns an array of all devices include in the group.
|
154
|
+
|
155
|
+
settings
|
156
|
+
#describes the updates that will occur when triggered
|
157
|
+
|
158
|
+
#method_missing is also included to retrieve some attributes
|
159
|
+
name
|
160
|
+
order
|
161
|
+
|
162
|
+
|
163
|
+
## Contributing
|
164
|
+
|
165
|
+
1. Fork it ( https://github.com/[my-github-username]/winker/fork )
|
166
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
167
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
168
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
169
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
module Winker
|
2
|
+
module ApiMethods
|
3
|
+
def get(path, params = nil)
|
4
|
+
response = super
|
5
|
+
@server_time_dif = Time.parse(response.headers["date"]) - Time.now
|
6
|
+
return response
|
7
|
+
end
|
8
|
+
|
9
|
+
def put(path, params = nil)
|
10
|
+
response = super
|
11
|
+
@server_time_dif = Time.parse(response.headers["date"]) - Time.now
|
12
|
+
return response
|
13
|
+
end
|
14
|
+
|
15
|
+
def post(path, params = nil)
|
16
|
+
response = super
|
17
|
+
@server_time_dif = Time.parse(response.headers["date"]) - Time.now
|
18
|
+
return response
|
19
|
+
end
|
20
|
+
|
21
|
+
def authorize
|
22
|
+
response = post("/oauth2/token", {client_id: Winker.client_id, client_secret: Winker.client_secret, username: Winker.username, password: Winker.password, grant_type: "password"})
|
23
|
+
@access_token = response.body["access_token"]
|
24
|
+
@refresh_token = response.body["refresh_token"]
|
25
|
+
@connection = nil
|
26
|
+
response
|
27
|
+
end
|
28
|
+
|
29
|
+
def devices
|
30
|
+
|
31
|
+
response = get("/users/me/wink_devices")
|
32
|
+
Winker::Device.load_devices(parse(response.body).data)
|
33
|
+
end
|
34
|
+
|
35
|
+
def groups
|
36
|
+
response = get("/users/me/groups")
|
37
|
+
Winker::Group.load_groups(parse(response.body).data)
|
38
|
+
end
|
39
|
+
|
40
|
+
def icons
|
41
|
+
response = get("/icons")
|
42
|
+
parse(response.body).data
|
43
|
+
end
|
44
|
+
|
45
|
+
def channels
|
46
|
+
response = get("/channels")
|
47
|
+
parse(response.body).data
|
48
|
+
end
|
49
|
+
|
50
|
+
def scenes
|
51
|
+
response = get("/users/me/scenes")
|
52
|
+
Winker::Scene.load_scenes(parse(response.body).data)
|
53
|
+
end
|
54
|
+
|
55
|
+
def get_scene(scene_id)
|
56
|
+
response = get("/scenes/#{scene_id}")
|
57
|
+
parse(response.body).data
|
58
|
+
end
|
59
|
+
|
60
|
+
# def update_scene(scene_id, options)
|
61
|
+
# response = put("/scenes/#{scene_id}")
|
62
|
+
# parse(response.body).data
|
63
|
+
# end
|
64
|
+
|
65
|
+
def activate_scene(scene_id)
|
66
|
+
response = post("/scenes/#{scene_id}/activate")
|
67
|
+
parse(response.body).data
|
68
|
+
end
|
69
|
+
|
70
|
+
def get_device(type, id)
|
71
|
+
response = get("/#{type}s/#{id}")
|
72
|
+
parse(response.body).data
|
73
|
+
end
|
74
|
+
|
75
|
+
def update_device(type, id, options)
|
76
|
+
response = put("/#{type}s/#{id}", options)
|
77
|
+
parse(response.body).data
|
78
|
+
end
|
79
|
+
|
80
|
+
def update_group(id, options)
|
81
|
+
response = post("/groups/#{id}/activate", options)
|
82
|
+
parse(response.body).data
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Winker
|
2
|
+
module Connection
|
3
|
+
def connection
|
4
|
+
@connection ||= Faraday.new(Winker.endpoint) do |conn|
|
5
|
+
conn.options[:timeout] = 5
|
6
|
+
conn.options[:open_timeout] = 2
|
7
|
+
|
8
|
+
conn.request :json
|
9
|
+
conn.response :json, :content_type => /\bjson$/
|
10
|
+
|
11
|
+
conn.authorization :bearer, Winker.access_token if Winker.access_token
|
12
|
+
conn.response :detailed_logger
|
13
|
+
|
14
|
+
conn.adapter Faraday.default_adapter # make requests with Net::HTTP
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def get(path, body = {})
|
19
|
+
body = MultiJson.dump(body) if Hash === body
|
20
|
+
connection.get(path) do |req|
|
21
|
+
req.body = body if body
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def post(path, body = {})
|
26
|
+
body = MultiJson.dump(body) if Hash === body
|
27
|
+
connection.post(path) do |req|
|
28
|
+
req.body = body if body
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def put(path, body = {})
|
33
|
+
body = MultiJson.dump(body) if Hash === body
|
34
|
+
connection.put(path) do |req|
|
35
|
+
req.body = body if body
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
|
2
|
+
require 'winker/devices/device_methods'
|
3
|
+
require 'winker/devices/generic_device'
|
4
|
+
require 'winker/devices/on_off'
|
5
|
+
require 'winker/devices/light_bulb'
|
6
|
+
require 'winker/devices/sensor_pod'
|
7
|
+
require 'winker/devices/unknown_device'
|
8
|
+
require 'winker/devices/hub'
|
9
|
+
|
10
|
+
module Winker
|
11
|
+
class Device
|
12
|
+
def self.load_devices(data)
|
13
|
+
data.map{|d| Winker::Device.new(d)}
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(obj_data)
|
17
|
+
@obj_data = obj_data
|
18
|
+
find_type_and_id
|
19
|
+
self.extend(eval("Winker::Devices::#{@type.classify}"))
|
20
|
+
end
|
21
|
+
|
22
|
+
def method_missing(method_sym, *arguments, &block)
|
23
|
+
if obj_data.respond_to?(method_sym)
|
24
|
+
obj_data.send(method_sym, *arguments, &block)
|
25
|
+
else
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
include Winker::Devices::DeviceMethods
|
31
|
+
include Winker::Devices::GenericDevice
|
32
|
+
include Winker::Devices::OnOff
|
33
|
+
include Winker::Devices::LightBulb
|
34
|
+
include Winker::Devices::SensorPod
|
35
|
+
include Winker::Devices::UnknownDevice
|
36
|
+
include Winker::Devices::Hub
|
37
|
+
# VALID_TYPES=%w{
|
38
|
+
# sensor_pod
|
39
|
+
# light_bulb
|
40
|
+
# garage_door
|
41
|
+
# binary_switch
|
42
|
+
# air_conditioner
|
43
|
+
# propane_tank
|
44
|
+
# outlet
|
45
|
+
# powerstrip
|
46
|
+
# piggy_bank
|
47
|
+
# eggtray
|
48
|
+
# cloud_clock
|
49
|
+
# alarm
|
50
|
+
# dial
|
51
|
+
# scene
|
52
|
+
# robot
|
53
|
+
# group
|
54
|
+
# }
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Winker
|
2
|
+
module Devices
|
3
|
+
module DeviceMethods
|
4
|
+
#hub must always be last since the hub_id is listed with every device
|
5
|
+
|
6
|
+
VALID_TYPES = %w{
|
7
|
+
sensor_pod
|
8
|
+
light_bulb
|
9
|
+
unknown_device
|
10
|
+
hub
|
11
|
+
}
|
12
|
+
|
13
|
+
WAIT_BLOCK_SLEEP = 1
|
14
|
+
WAIT_BLOCK_TIMEOUT = 20.seconds
|
15
|
+
|
16
|
+
|
17
|
+
attr_accessor :type, :id, :obj_data, :updated_at
|
18
|
+
|
19
|
+
def find_type_and_id
|
20
|
+
@type = VALID_TYPES.find{|t| @obj_data.singleton_methods.map(&:to_s).include?("#{t}_id")}
|
21
|
+
@id = @obj_data.send("#{@type}_id")
|
22
|
+
@updated_at = 2.weeks.ago
|
23
|
+
end
|
24
|
+
|
25
|
+
def wait_for_update(boolean_proc, options = {}, &block)
|
26
|
+
options = {
|
27
|
+
timeout: WAIT_BLOCK_TIMEOUT
|
28
|
+
}.merge(options)
|
29
|
+
start = Time.now
|
30
|
+
until (success = boolean_proc.call) || Time.now > start+options[:timeout]
|
31
|
+
result = yield
|
32
|
+
sleep WAIT_BLOCK_SLEEP
|
33
|
+
end
|
34
|
+
if success
|
35
|
+
return result
|
36
|
+
else
|
37
|
+
raise "Device #{self.type} #{self.name} not updated."
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Winker
|
2
|
+
module Devices
|
3
|
+
module GenericDevice
|
4
|
+
def refresh
|
5
|
+
@obj_data = Winker.get_device(@type, @id)
|
6
|
+
end
|
7
|
+
|
8
|
+
def update(options)
|
9
|
+
@updated_at = Time.now + Winker.server_time_dif
|
10
|
+
Winker.update_device(@type, @id, options)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Winker
|
2
|
+
module Devices
|
3
|
+
module LightBulb
|
4
|
+
include OnOff
|
5
|
+
|
6
|
+
def updates_finished?
|
7
|
+
check_last_brightness
|
8
|
+
check_last_powered
|
9
|
+
return true
|
10
|
+
end
|
11
|
+
|
12
|
+
def check_last_brightness
|
13
|
+
wait_for_update( Proc.new{@updated_at < @obj_data.last_reading.brightness_updated_at.to_time}) do
|
14
|
+
self.refresh
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.extended(obj)
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def brightness
|
23
|
+
check_last_brightness
|
24
|
+
@obj_data.last_reading.brightness
|
25
|
+
end
|
26
|
+
|
27
|
+
def brightness=(_brightness)
|
28
|
+
#set brightness level
|
29
|
+
if _brightness == 0
|
30
|
+
update(desired_state: {powered: "false", brightness: _brightness})
|
31
|
+
else
|
32
|
+
update(desired_state: {powered: "true", brightness: _brightness})
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Winker
|
2
|
+
module Devices
|
3
|
+
module OnOff
|
4
|
+
def updates_finished?
|
5
|
+
check_last_powered
|
6
|
+
return true
|
7
|
+
end
|
8
|
+
|
9
|
+
def check_last_powered
|
10
|
+
wait_for_update( Proc.new{@updated_at < @obj_data.last_reading.powered_updated_at.to_time}) do
|
11
|
+
self.refresh
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def powered?
|
16
|
+
check_last_powered
|
17
|
+
@obj_data.last_reading.powered
|
18
|
+
end
|
19
|
+
|
20
|
+
def on
|
21
|
+
#turn on device
|
22
|
+
update(desired_state: {powered: "true"})
|
23
|
+
end
|
24
|
+
|
25
|
+
def off
|
26
|
+
#turn off device
|
27
|
+
update(desired_state: {powered: "false"})
|
28
|
+
end
|
29
|
+
|
30
|
+
def off?
|
31
|
+
!powered?
|
32
|
+
end
|
33
|
+
|
34
|
+
alias on? powered?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/winker/float.rb
ADDED
data/lib/winker/group.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
module Winker
|
2
|
+
|
3
|
+
class Group
|
4
|
+
|
5
|
+
attr_accessor :type, :id, :obj_data
|
6
|
+
|
7
|
+
def self.load_groups(data)
|
8
|
+
data.map{|d| Winker::Group.new(d)}
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(obj_data)
|
12
|
+
@obj_data = obj_data
|
13
|
+
@id = @obj_data.group_id
|
14
|
+
end
|
15
|
+
|
16
|
+
def members
|
17
|
+
devices.select{|d| @obj_data.members.map{|m| m[:object_id]}.include?(d.id)}
|
18
|
+
end
|
19
|
+
|
20
|
+
def on
|
21
|
+
Winker.update_group(@id, {desired_state: {powered: "true"}})
|
22
|
+
end
|
23
|
+
|
24
|
+
def off
|
25
|
+
Winker.update_group(@id, {desired_state: {powered: "false"}})
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def brightness=(_brightness)
|
30
|
+
#set brightness level
|
31
|
+
Winker.update_group(@id, {desired_state: {powered: "true", brightness: _brightness}})
|
32
|
+
end
|
33
|
+
|
34
|
+
def method_missing(method_sym, *arguments, &block)
|
35
|
+
|
36
|
+
if obj_data.respond_to?(method_sym)
|
37
|
+
obj_data.send(method_sym, *arguments, &block)
|
38
|
+
else
|
39
|
+
super
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
|
46
|
+
def devices
|
47
|
+
@devices ||= Winker.devices
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
data/lib/winker/scene.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
module Winker
|
2
|
+
|
3
|
+
class Scene
|
4
|
+
|
5
|
+
attr_accessor :type, :id, :obj_data
|
6
|
+
|
7
|
+
def self.load_scenes(data)
|
8
|
+
data.map{|s| Winker::Scene.new(s)}
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(obj_data)
|
12
|
+
@obj_data = obj_data
|
13
|
+
@id = @obj_data.scene_id
|
14
|
+
end
|
15
|
+
|
16
|
+
def members
|
17
|
+
devices.select{|d| @obj_data.members.map{|m| m[:object_id]}.include?(d.id)}
|
18
|
+
end
|
19
|
+
|
20
|
+
def settings
|
21
|
+
@obj_data.members
|
22
|
+
end
|
23
|
+
|
24
|
+
def activate
|
25
|
+
Winker.activate_scene(self.id)
|
26
|
+
end
|
27
|
+
|
28
|
+
def method_missing(method_sym, *arguments, &block)
|
29
|
+
|
30
|
+
if obj_data.respond_to?(method_sym)
|
31
|
+
obj_data.send(method_sym, *arguments, &block)
|
32
|
+
else
|
33
|
+
super
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
|
40
|
+
def devices
|
41
|
+
@devices ||= Winker.devices
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Winker
|
2
|
+
#TODO make temperture class for easy conversion between F and C
|
3
|
+
# this is not included in the project at this moment
|
4
|
+
class Temperature < Numeric
|
5
|
+
DEFAULT_SCALE = "f"
|
6
|
+
attr_accessor :reading, :scale, :display_scale
|
7
|
+
|
8
|
+
def initialize(temp, scale = DEFAULT_SCALE, display_scale = DEFAULT_SCALE)
|
9
|
+
@reading = temp
|
10
|
+
@scale = scale
|
11
|
+
@display_scale = display_scale
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
temp.to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_i
|
19
|
+
temp.to_i
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_f
|
23
|
+
temp.to_f
|
24
|
+
end
|
25
|
+
|
26
|
+
def temp
|
27
|
+
case
|
28
|
+
when scale == display_scale
|
29
|
+
return reading
|
30
|
+
when scale == "f" && display_scale == "c"
|
31
|
+
return (reading - 32) * 5.0 / 9
|
32
|
+
when scale == "c" && display_scale == "f"
|
33
|
+
return (reading * 9.0 / 5) + 32
|
34
|
+
else
|
35
|
+
raise "Doesn't support #{scale} temp scale"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/winker.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require "winker/version"
|
2
|
+
|
3
|
+
|
4
|
+
require 'faraday'
|
5
|
+
require 'faraday_middleware'
|
6
|
+
require 'faraday/detailed_logger'
|
7
|
+
require 'hashie'
|
8
|
+
require 'active_support'
|
9
|
+
require 'active_support/core_ext'
|
10
|
+
require 'multi_json'
|
11
|
+
|
12
|
+
|
13
|
+
require 'winker/float'
|
14
|
+
require 'winker/device'
|
15
|
+
require 'winker/group'
|
16
|
+
require 'winker/scene'
|
17
|
+
require 'winker/connection'
|
18
|
+
require 'winker/api_methods'
|
19
|
+
|
20
|
+
module Winker
|
21
|
+
|
22
|
+
module Parser
|
23
|
+
def parse(body)
|
24
|
+
case body
|
25
|
+
when Hash
|
26
|
+
body.each do |k,v|
|
27
|
+
body[k] = parse(v)
|
28
|
+
end
|
29
|
+
OpenStruct.new(body)
|
30
|
+
when Array
|
31
|
+
body.map { |item| parse(item) }
|
32
|
+
else
|
33
|
+
body
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
module Configuration
|
39
|
+
attr_accessor :client_id, :client_secret, :access_token, :refresh_token, :username, :password, :endpoint, :server_time_dif
|
40
|
+
|
41
|
+
def configure
|
42
|
+
yield self
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
extend Parser
|
47
|
+
extend Configuration
|
48
|
+
extend Connection
|
49
|
+
extend ApiMethods
|
50
|
+
|
51
|
+
end
|
data/winker.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'winker/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "winker"
|
8
|
+
spec.version = Winker::VERSION
|
9
|
+
spec.authors = ["Kelly Mahan"]
|
10
|
+
spec.email = ["kmahan@kmahan.com"]
|
11
|
+
spec.summary = %q{Winker is a gem written to support the wink api and any other associated platforms.}
|
12
|
+
spec.description = %q{Winker is a gem written to support the wink api and any other associated platforms.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
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"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_dependency "faraday", "~> 0.9"
|
24
|
+
spec.add_dependency "faraday_middleware", "~> 0.9"
|
25
|
+
spec.add_dependency "faraday-detailed_logger", "~> 1.0"
|
26
|
+
spec.add_dependency "hashie", "~> 3.4"
|
27
|
+
spec.add_dependency "activesupport"
|
28
|
+
spec.add_dependency "multi_json"
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: winker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kelly Mahan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: faraday
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.9'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.9'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: faraday_middleware
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.9'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.9'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: faraday-detailed_logger
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: hashie
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.4'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.4'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: activesupport
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: multi_json
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description: Winker is a gem written to support the wink api and any other associated
|
126
|
+
platforms.
|
127
|
+
email:
|
128
|
+
- kmahan@kmahan.com
|
129
|
+
executables: []
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- ".gitignore"
|
134
|
+
- Gemfile
|
135
|
+
- LICENSE.txt
|
136
|
+
- README.md
|
137
|
+
- Rakefile
|
138
|
+
- lib/winker.rb
|
139
|
+
- lib/winker/api_methods.rb
|
140
|
+
- lib/winker/connection.rb
|
141
|
+
- lib/winker/device.rb
|
142
|
+
- lib/winker/devices/device_methods.rb
|
143
|
+
- lib/winker/devices/generic_device.rb
|
144
|
+
- lib/winker/devices/hub.rb
|
145
|
+
- lib/winker/devices/light_bulb.rb
|
146
|
+
- lib/winker/devices/on_off.rb
|
147
|
+
- lib/winker/devices/sensor_pod.rb
|
148
|
+
- lib/winker/devices/unknown_device.rb
|
149
|
+
- lib/winker/float.rb
|
150
|
+
- lib/winker/group.rb
|
151
|
+
- lib/winker/scene.rb
|
152
|
+
- lib/winker/temperature.rb
|
153
|
+
- lib/winker/version.rb
|
154
|
+
- winker.gemspec
|
155
|
+
homepage: ''
|
156
|
+
licenses:
|
157
|
+
- MIT
|
158
|
+
metadata: {}
|
159
|
+
post_install_message:
|
160
|
+
rdoc_options: []
|
161
|
+
require_paths:
|
162
|
+
- lib
|
163
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
168
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - ">="
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '0'
|
173
|
+
requirements: []
|
174
|
+
rubyforge_project:
|
175
|
+
rubygems_version: 2.2.2
|
176
|
+
signing_key:
|
177
|
+
specification_version: 4
|
178
|
+
summary: Winker is a gem written to support the wink api and any other associated
|
179
|
+
platforms.
|
180
|
+
test_files: []
|