mios 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +58 -0
- data/Rakefile +8 -0
- data/lib/mios/action.rb +25 -0
- data/lib/mios/device.rb +93 -0
- data/lib/mios/interface.rb +68 -0
- data/lib/mios/job.rb +79 -0
- data/lib/mios/services/camera1.rb +9 -0
- data/lib/mios/services/dimmable_light1.rb +20 -0
- data/lib/mios/services/door_lock1.rb +38 -0
- data/lib/mios/services/energy_metering1.rb +13 -0
- data/lib/mios/services/generic_sensor1.rb +9 -0
- data/lib/mios/services/ha_device1.rb +17 -0
- data/lib/mios/services/humidity_sensor1.rb +14 -0
- data/lib/mios/services/light_sensor1.rb +21 -0
- data/lib/mios/services/scene_controller1.rb +9 -0
- data/lib/mios/services/security_sensor1.rb +33 -0
- data/lib/mios/services/switch_power1.rb +25 -0
- data/lib/mios/services/temperature_sensor1.rb +13 -0
- data/lib/mios/services/window_covering1.rb +21 -0
- data/lib/mios/services/zwave_device1.rb +9 -0
- data/lib/mios/services/zwave_network1.rb +9 -0
- data/lib/mios/version.rb +3 -0
- data/lib/mios.rb +7 -0
- data/mios.gemspec +26 -0
- data/spec/random_spec.rb +8 -0
- data/spec/spec_helper.rb +5 -0
- metadata +163 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Kelley Reynolds
|
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,58 @@
|
|
1
|
+
# MiOS
|
2
|
+
|
3
|
+
Gem that uses the URL API for the Vera family of products from [MiCasaVerde](http://micasaverde.com).
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'mios'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install mios
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
MiOS works on a job queue. If you wish to change an attribute or the status of a particular device, you must submit a
|
22
|
+
job to MiOS and wait for it to be succeed or fail or require a requeue. Most of this functionality is hidden behind the scenes
|
23
|
+
and an idiomatic synchronous closure interface is exposed that manages it all for you, as you'll see below. Most methods can also
|
24
|
+
be used asynchronously but you need to know what you are doing as this is not really an event-driven system and inconsistencies can
|
25
|
+
occur if used improperly.
|
26
|
+
|
27
|
+
### Create a reference to your local MiOS device
|
28
|
+
mios = MiOS::Interface.new('http://192.168.15.1:3480')
|
29
|
+
|
30
|
+
### Devices could be anything of course, assuming here the first is a switch
|
31
|
+
switch = mios.devices[0]
|
32
|
+
|
33
|
+
### Turn the switch off (light switch or outlet or anything classed as a switch)
|
34
|
+
switch.off!
|
35
|
+
|
36
|
+
### The job object is returned from calls that require API calls
|
37
|
+
job = switch.on!
|
38
|
+
|
39
|
+
### Execute some code once the job has finished
|
40
|
+
switch.off! { |obj|
|
41
|
+
puts "The #{obj.name} is now off"
|
42
|
+
}
|
43
|
+
puts "This will get printed once the switch is off and the block has been executed"
|
44
|
+
|
45
|
+
### Execute some code asynchronously from the job
|
46
|
+
switch.on!(true) { |obj|
|
47
|
+
puts "The #{obj.name} is now on"
|
48
|
+
}
|
49
|
+
puts "This will output immediately"
|
50
|
+
sleep(5) # Sleep to wait for the thread to finish, will clean this up later
|
51
|
+
|
52
|
+
## Contributing
|
53
|
+
|
54
|
+
1. Fork it
|
55
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
56
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
57
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
58
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/lib/mios/action.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
module MiOS
|
4
|
+
class Action
|
5
|
+
def initialize(device, service_id, action, parameters={})
|
6
|
+
@device, @service_id, @action, @parameters = device, service_id, action, parameters
|
7
|
+
end
|
8
|
+
|
9
|
+
def take(async=false, &block)
|
10
|
+
response = @device.class.get url
|
11
|
+
# Are there ever more than one jobs from a device action?
|
12
|
+
Job.new(@device, response.values.first['JobID'], async, &block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def url
|
16
|
+
url = "/data_request?output_format=json&id=action"
|
17
|
+
url += "&DeviceNum=#{@device.id}"
|
18
|
+
url += "&action=#{@action}"
|
19
|
+
url += "&serviceId=#{@service_id}&"
|
20
|
+
url += @parameters.map { |k, v|
|
21
|
+
"#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}"
|
22
|
+
}.join("&")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/mios/device.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
module MiOS
|
2
|
+
class Device
|
3
|
+
|
4
|
+
class << self
|
5
|
+
def new(uri, *args)
|
6
|
+
Class.new(AbstractInterface) { |klass|
|
7
|
+
klass.base_uri(uri)
|
8
|
+
}.new(*args)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class AbstractInterface
|
13
|
+
include HTTParty
|
14
|
+
format :json
|
15
|
+
|
16
|
+
attr_reader :attributes
|
17
|
+
|
18
|
+
def initialize(data)
|
19
|
+
parse(data)
|
20
|
+
end
|
21
|
+
|
22
|
+
def inspect
|
23
|
+
"#<MiOS::Device:0x#{'%x' % (self.object_id << 1)} name=#{@attributes['name']}>"
|
24
|
+
end
|
25
|
+
|
26
|
+
def method_missing(method, *args)
|
27
|
+
if @attributes.has_key?(method.to_s)
|
28
|
+
@attributes[method.to_s]
|
29
|
+
else
|
30
|
+
super
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def reload
|
35
|
+
parse(self.class.get("/data_request?id=status&DeviceNum=#{id}").parsed_response["Device_Num_#{id}"], true)
|
36
|
+
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def set(urn, action, params, async=false, &block)
|
43
|
+
MiOS::Action.new(self, urn, action, params).take(async, &block)
|
44
|
+
end
|
45
|
+
|
46
|
+
def timestamp_for(urn, key)
|
47
|
+
Time.at integer_for(urn, key)
|
48
|
+
end
|
49
|
+
|
50
|
+
def boolean_for(urn, key)
|
51
|
+
integer_for(urn, key) == 1
|
52
|
+
end
|
53
|
+
|
54
|
+
def integer_for(urn, key)
|
55
|
+
value_for(urn, key).to_i
|
56
|
+
end
|
57
|
+
|
58
|
+
def value_for(urn, key)
|
59
|
+
@states.each do |state_hash|
|
60
|
+
if state_hash['service'] == urn
|
61
|
+
if state_hash['variable'] == key
|
62
|
+
return state_hash['value']
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
|
70
|
+
def parse(data, skip_attributes=false)
|
71
|
+
|
72
|
+
@attributes = Hash[
|
73
|
+
data.select { |k, v|
|
74
|
+
!data[k].kind_of?(Hash) and !data[k].kind_of?(Array)
|
75
|
+
}.to_a
|
76
|
+
] unless skip_attributes
|
77
|
+
|
78
|
+
@states = data['states']
|
79
|
+
@states.map { |state|
|
80
|
+
state['service'].split(":").last
|
81
|
+
}.uniq.each { |service|
|
82
|
+
if MiOS::Services.const_defined?(service)
|
83
|
+
extend MiOS::Services.const_get(service)
|
84
|
+
else
|
85
|
+
$stderr.puts "WARNING: #{service} not yet supported"
|
86
|
+
end
|
87
|
+
}
|
88
|
+
|
89
|
+
true
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module MiOS
|
2
|
+
class Interface
|
3
|
+
|
4
|
+
class << self
|
5
|
+
def new(uri, *args)
|
6
|
+
Class.new(AbstractInterface) { |klass|
|
7
|
+
klass.base_uri(uri)
|
8
|
+
}.new(*args)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class AbstractInterface
|
13
|
+
include HTTParty
|
14
|
+
format :json
|
15
|
+
|
16
|
+
attr_reader :attributes
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
refresh!
|
20
|
+
end
|
21
|
+
|
22
|
+
def method_missing(method, *args)
|
23
|
+
if @attributes.has_key?(method.to_s)
|
24
|
+
@attributes[method.to_s]
|
25
|
+
else
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def inspect
|
31
|
+
"#<MiOS::Interface:0x#{'%x' % (self.object_id << 1)} @attributes=#{@attributes.inspect}>"
|
32
|
+
end
|
33
|
+
|
34
|
+
def refresh!
|
35
|
+
data = self.class.get "/data_request?id=user_data"
|
36
|
+
@attributes = Hash[
|
37
|
+
data.select { |k, v|
|
38
|
+
!data[k].kind_of?(Hash) and !data[k].kind_of?(Array)
|
39
|
+
}.map { |k, v|
|
40
|
+
[k.downcase, v]
|
41
|
+
}
|
42
|
+
]
|
43
|
+
# Convert some time objects
|
44
|
+
['loadtime', 'devicesync'].each do |attr|
|
45
|
+
@attributes[attr] = Time.at(@attributes[attr].to_i)
|
46
|
+
end
|
47
|
+
|
48
|
+
@devices = Hash[
|
49
|
+
data['devices'].map { |device|
|
50
|
+
[device['id'], Device.new(self.class.base_uri, device)]
|
51
|
+
}
|
52
|
+
]
|
53
|
+
|
54
|
+
true
|
55
|
+
end
|
56
|
+
|
57
|
+
def categories
|
58
|
+
@devices.values.map { |device|
|
59
|
+
device.category
|
60
|
+
}.uniq.sort
|
61
|
+
end
|
62
|
+
|
63
|
+
def devices; @devices.values; end
|
64
|
+
|
65
|
+
def device_names; devices.map(&:name); end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/mios/job.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
|
3
|
+
module MiOS
|
4
|
+
module Error
|
5
|
+
class JobNonexistent < StandardError; end
|
6
|
+
class JobError < StandardError; end
|
7
|
+
class JobAborted < StandardError; end
|
8
|
+
class JobRequeue < StandardError; end
|
9
|
+
class JobTimeout < StandardError; end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Job
|
13
|
+
Status = {
|
14
|
+
-1 => "Nonexistent",
|
15
|
+
0 => "Waiting",
|
16
|
+
1 => "In progress",
|
17
|
+
2 => "Error",
|
18
|
+
3 => "Aborted",
|
19
|
+
4 => "Completed",
|
20
|
+
5 => "Waiting for callback",
|
21
|
+
6 => "Requeue",
|
22
|
+
7 => "In progress with pending data"
|
23
|
+
}
|
24
|
+
attr_reader :id
|
25
|
+
|
26
|
+
def initialize(obj, id, async=false, &block)
|
27
|
+
@obj, @id = obj, id
|
28
|
+
reload_status!
|
29
|
+
|
30
|
+
if block_given?
|
31
|
+
if async
|
32
|
+
Thread.new do
|
33
|
+
when_complete(&block)
|
34
|
+
end
|
35
|
+
else
|
36
|
+
when_complete(&block)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def when_complete(&block)
|
42
|
+
raise Error::JobTimeout if !exists?
|
43
|
+
Timeout::timeout(20) do
|
44
|
+
sleep_interval = 0.25
|
45
|
+
|
46
|
+
# If the job is still processing, wait a bit and try again
|
47
|
+
while waiting? || in_progress? || waiting_for_callback? || in_progress_with_pending_data? do
|
48
|
+
sleep(sleep_interval += 0.25)
|
49
|
+
reload_status!
|
50
|
+
end
|
51
|
+
raise JobError if error?
|
52
|
+
raise JobAborted if aborted?
|
53
|
+
raise JobRequeue if requeue?
|
54
|
+
end
|
55
|
+
yield @obj.reload
|
56
|
+
rescue Timeout::Error
|
57
|
+
$stderr.puts "Timed out waiting for job status to become complete"
|
58
|
+
raise Error::JobTimeout
|
59
|
+
end
|
60
|
+
|
61
|
+
def exists?; status != -1; end
|
62
|
+
def waiting?; status == 0; end
|
63
|
+
def in_progress?; status == 1; end
|
64
|
+
def error?; status == 2; end
|
65
|
+
def aborted?; status == 3; end
|
66
|
+
def completed?; status == 4; end
|
67
|
+
def waiting_for_callback?; status == 5; end
|
68
|
+
def requeue?; status == 6; end
|
69
|
+
def in_progress_with_pending_data?; status == 7; end
|
70
|
+
|
71
|
+
def status
|
72
|
+
@status || reload_status!
|
73
|
+
end
|
74
|
+
|
75
|
+
def reload_status!
|
76
|
+
@status = @obj.class.get("/data_request?id=jobstatus&job=#{@id}&plugin=zwave")['status']
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module MiOS
|
2
|
+
module Services
|
3
|
+
module Dimming1
|
4
|
+
def self.extended(base)
|
5
|
+
base.instance_variable_set("@dimming1_urn", "urn:upnp-org:serviceId:Dimming1")
|
6
|
+
end
|
7
|
+
|
8
|
+
def level
|
9
|
+
integer_for(@dimming1_urn, 'LoadLevelStatus')
|
10
|
+
end
|
11
|
+
|
12
|
+
def set_level!(new_level, async=false, &block)
|
13
|
+
new_level = new_load_level.to_i
|
14
|
+
new_level = 100 if new_load_level > 100
|
15
|
+
new_level = 0 if new_load_level < 0
|
16
|
+
set(@dimming1_urn, "SetLoadLevelTarget", {"newLoadLevelTarget" => new_level}, async, &block)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module MiOS
|
2
|
+
module Services
|
3
|
+
module DoorLock1
|
4
|
+
def self.extended(base)
|
5
|
+
base.instance_variable_set("@doorlock1_urn", "urn:micasaverde-com:serviceId:DoorLock1")
|
6
|
+
end
|
7
|
+
|
8
|
+
def locked?
|
9
|
+
boolean_for(@doorlock1_urn, 'Status')
|
10
|
+
end
|
11
|
+
|
12
|
+
def unlocked?
|
13
|
+
!locked?
|
14
|
+
end
|
15
|
+
|
16
|
+
def pincodes
|
17
|
+
tmp = value_for(@doorlock1_urn, 'PinCodes')
|
18
|
+
tmp.gsub!(/^<[^>]+>/, '').split("\t")
|
19
|
+
end
|
20
|
+
|
21
|
+
def lock!(async=false, &block)
|
22
|
+
set(@doorlock1_urn, "SetTarget", {"newTargetValue" => 1}, async, &block)
|
23
|
+
end
|
24
|
+
|
25
|
+
def unlock!(async=false, &block)
|
26
|
+
set(@doorlock1_urn, "SetTarget", {"newTargetValue" => 0}, async, &block)
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_pin(name, pin, index, async=false, &block)
|
30
|
+
set(@doorlock1_urn, "SetPin", {"UserCodeName" => name, "newPin" => pin, "user" => index}, async, &block)
|
31
|
+
end
|
32
|
+
|
33
|
+
def clear_pin(index, async=false, &block)
|
34
|
+
set(@doorlock1_urn, "ClearPin", {"UserCode" => index}, async, &block)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module MiOS
|
2
|
+
module Services
|
3
|
+
module EnergyMetering1
|
4
|
+
def self.extended(base)
|
5
|
+
base.instance_variable_set("@energymetering1_urn", "urn:upnp-org:serviceId:EnergyMetering1")
|
6
|
+
end
|
7
|
+
|
8
|
+
def watts
|
9
|
+
integer_for(@energymetering1_urn, 'Watts')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module MiOS
|
2
|
+
module Services
|
3
|
+
module HaDevice1
|
4
|
+
def self.extended(base)
|
5
|
+
base.instance_variable_set("@hadevice1_urn", "urn:micasaverde-com:serviceId:HaDevice1")
|
6
|
+
end
|
7
|
+
|
8
|
+
def battery_level
|
9
|
+
integer_for(@hadevice1_urn, "BatteryLevel")
|
10
|
+
end
|
11
|
+
|
12
|
+
def battery_date
|
13
|
+
timestamp_for(@hadevice1_urn, "BatteryDate")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# NOTE: Currently untested with a real humidity sensor
|
2
|
+
module MiOS
|
3
|
+
module Services
|
4
|
+
module HumiditySensor1
|
5
|
+
def self.extended(base)
|
6
|
+
base.instance_variable_set("@humiditysensor1_urn", "urn:upnp-org:serviceId:HumiditySensor1")
|
7
|
+
end
|
8
|
+
|
9
|
+
def humidity
|
10
|
+
integer_for(@humiditysensor1_urn, 'CurrentHumidity')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module MiOS
|
2
|
+
module Services
|
3
|
+
module LightSensor1
|
4
|
+
def self.extended(base)
|
5
|
+
base.instance_variable_set("@lightsensor1_urn", "urn:micasaverde-com:serviceId:LightSensor1")
|
6
|
+
end
|
7
|
+
|
8
|
+
def level
|
9
|
+
@states.each do |state_hash|
|
10
|
+
if state_hash['service'] == @lightsensor1_urn
|
11
|
+
if state_hash['variable'] == "CurrentLevel"
|
12
|
+
return state_hash['value'].to_i
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
return nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module MiOS
|
2
|
+
module Services
|
3
|
+
module SecuritySensor1
|
4
|
+
def self.extended(base)
|
5
|
+
base.instance_variable_set("@securitysensor1_urn", "urn:micasaverde-com:serviceId:SecuritySensor1")
|
6
|
+
end
|
7
|
+
|
8
|
+
def tripped?
|
9
|
+
boolean_for(@securitysensor1_urn, 'Tripped')
|
10
|
+
end
|
11
|
+
|
12
|
+
def armed?
|
13
|
+
boolean_for(@securitysensor1_urn, 'Armed')
|
14
|
+
end
|
15
|
+
|
16
|
+
def disarmed?
|
17
|
+
!armed?
|
18
|
+
end
|
19
|
+
|
20
|
+
def lasttrip
|
21
|
+
timestamp_for(@securitysensor1_urn, 'LastTrip')
|
22
|
+
end
|
23
|
+
|
24
|
+
def arm!(async=false, &block)
|
25
|
+
set(@securitysensor1_urn, "SetArmed", {"newArmedValue" => 1}, async, &block)
|
26
|
+
end
|
27
|
+
|
28
|
+
def disarm!(async=false, &block)
|
29
|
+
set(@securitysensor1_urn, "SetArmed", {"newArmedValue" => 0}, async, &block)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module MiOS
|
2
|
+
module Services
|
3
|
+
module SwitchPower1
|
4
|
+
def self.extended(base)
|
5
|
+
base.instance_variable_set("@switchpower1_urn", "urn:upnp-org:serviceId:SwitchPower1")
|
6
|
+
end
|
7
|
+
|
8
|
+
def on?
|
9
|
+
boolean_for(@switchpower1_urn, 'Status')
|
10
|
+
end
|
11
|
+
|
12
|
+
def off?
|
13
|
+
!on?
|
14
|
+
end
|
15
|
+
|
16
|
+
def on!(async=false, &block)
|
17
|
+
set(@switchpower1_urn, "SetTarget", {"newTargetValue" => 1}, async, &block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def off!(async=false, &block)
|
21
|
+
set(@switchpower1_urn, "SetTarget", {"newTargetValue" => 0}, async, &block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module MiOS
|
2
|
+
module Services
|
3
|
+
module TemperatureSensor1
|
4
|
+
def self.extended(base)
|
5
|
+
base.instance_variable_set("@temperaturesensor1_urn", "urn:upnp-org:serviceId:TemperatureSensor1")
|
6
|
+
end
|
7
|
+
|
8
|
+
def temperature
|
9
|
+
integer_for(@temperaturesensor1_urn, 'CurrentTemperature')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module MiOS
|
2
|
+
module Services
|
3
|
+
module WindowCovering1
|
4
|
+
def self.extended(base)
|
5
|
+
base.instance_variable_set("@windowcovering1_urn", "urn:upnp-org:serviceId:WindowCovering1")
|
6
|
+
end
|
7
|
+
|
8
|
+
def up!(async=false, &block)
|
9
|
+
set(@windowcovering1_urn, "Up", async, &block)
|
10
|
+
end
|
11
|
+
|
12
|
+
def down!(async=false, &block)
|
13
|
+
set(@windowcovering1_urn, "Down", async, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def stop!(async=false, &block)
|
17
|
+
set(@windowcovering1_urn, "Stop", async, &block)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/mios/version.rb
ADDED
data/lib/mios.rb
ADDED
data/mios.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'mios/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "mios"
|
8
|
+
gem.version = MiOS::VERSION
|
9
|
+
gem.authors = ["Kelley Reynolds"]
|
10
|
+
gem.email = ["kelley.reynolds@rubyscale.com"]
|
11
|
+
gem.description = %q{Object-oriented interactions with MiOS from MiCasaVerde}
|
12
|
+
gem.summary = %q{Object-oriented interactions with MiOS from MiCasaVerde}
|
13
|
+
gem.homepage = ""
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_dependency "httparty", ">= 0.9.0"
|
21
|
+
|
22
|
+
gem.add_development_dependency "rspec", ">= 2.8.0"
|
23
|
+
gem.add_development_dependency "syntax"
|
24
|
+
gem.add_development_dependency "rake", ">= 0.9.2"
|
25
|
+
gem.add_development_dependency "yard", ">= 0.7.2"
|
26
|
+
end
|
data/spec/random_spec.rb
ADDED
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mios
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kelley Reynolds
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-10-07 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: httparty
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.9.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.9.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 2.8.0
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 2.8.0
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: syntax
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.9.2
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.9.2
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: yard
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 0.7.2
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 0.7.2
|
94
|
+
description: Object-oriented interactions with MiOS from MiCasaVerde
|
95
|
+
email:
|
96
|
+
- kelley.reynolds@rubyscale.com
|
97
|
+
executables: []
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- .gitignore
|
102
|
+
- Gemfile
|
103
|
+
- LICENSE.txt
|
104
|
+
- README.md
|
105
|
+
- Rakefile
|
106
|
+
- lib/mios.rb
|
107
|
+
- lib/mios/action.rb
|
108
|
+
- lib/mios/device.rb
|
109
|
+
- lib/mios/interface.rb
|
110
|
+
- lib/mios/job.rb
|
111
|
+
- lib/mios/services/camera1.rb
|
112
|
+
- lib/mios/services/dimmable_light1.rb
|
113
|
+
- lib/mios/services/door_lock1.rb
|
114
|
+
- lib/mios/services/energy_metering1.rb
|
115
|
+
- lib/mios/services/generic_sensor1.rb
|
116
|
+
- lib/mios/services/ha_device1.rb
|
117
|
+
- lib/mios/services/humidity_sensor1.rb
|
118
|
+
- lib/mios/services/light_sensor1.rb
|
119
|
+
- lib/mios/services/scene_controller1.rb
|
120
|
+
- lib/mios/services/security_sensor1.rb
|
121
|
+
- lib/mios/services/switch_power1.rb
|
122
|
+
- lib/mios/services/temperature_sensor1.rb
|
123
|
+
- lib/mios/services/window_covering1.rb
|
124
|
+
- lib/mios/services/zwave_device1.rb
|
125
|
+
- lib/mios/services/zwave_network1.rb
|
126
|
+
- lib/mios/version.rb
|
127
|
+
- mios.gemspec
|
128
|
+
- spec/random_spec.rb
|
129
|
+
- spec/spec_helper.rb
|
130
|
+
homepage: ''
|
131
|
+
licenses: []
|
132
|
+
post_install_message:
|
133
|
+
rdoc_options: []
|
134
|
+
require_paths:
|
135
|
+
- lib
|
136
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
segments:
|
143
|
+
- 0
|
144
|
+
hash: -1148143416777399406
|
145
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
|
+
none: false
|
147
|
+
requirements:
|
148
|
+
- - ! '>='
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '0'
|
151
|
+
segments:
|
152
|
+
- 0
|
153
|
+
hash: -1148143416777399406
|
154
|
+
requirements: []
|
155
|
+
rubyforge_project:
|
156
|
+
rubygems_version: 1.8.23
|
157
|
+
signing_key:
|
158
|
+
specification_version: 3
|
159
|
+
summary: Object-oriented interactions with MiOS from MiCasaVerde
|
160
|
+
test_files:
|
161
|
+
- spec/random_spec.rb
|
162
|
+
- spec/spec_helper.rb
|
163
|
+
has_rdoc:
|