mios 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mios.gemspec
4
+ gemspec
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
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake'
4
+ require 'rspec/core'
5
+ require 'rspec/core/rake_task'
6
+
7
+ require 'yard'
8
+ YARD::Rake::YardocTask.new
@@ -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
@@ -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,9 @@
1
+ module MiOS
2
+ module Services
3
+ module Camera1
4
+ def self.extended(base)
5
+ base.instance_variable_set("@camera1_urn", "urn:micasaverde-com:serviceId:Camera1")
6
+ end
7
+ end
8
+ end
9
+ 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,9 @@
1
+ module MiOS
2
+ module Services
3
+ module GenericSensor1
4
+ def self.extended(base)
5
+ base.instance_variable_set("@genericsensor1_urn", "urn:micasaverde-com:serviceId:GenericSensor1")
6
+ end
7
+ end
8
+ end
9
+ 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,9 @@
1
+ module MiOS
2
+ module Services
3
+ module SceneController1
4
+ def self.extended(base)
5
+ base.instance_variable_set("@scenecontroller1_urn", "urn:micasaverde-com:serviceId:SceneController1")
6
+ end
7
+ end
8
+ end
9
+ 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
@@ -0,0 +1,9 @@
1
+ module MiOS
2
+ module Services
3
+ module ZWaveDevice1
4
+ def self.extended(base)
5
+ base.instance_variable_set("@zwavedevice1_urn", "urn:micasaverde-com:serviceId:ZWaveDevice1")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module MiOS
2
+ module Services
3
+ module ZWaveNetwork1
4
+ def self.extended(base)
5
+ base.instance_variable_set("@zwavenetwork1_urn", "urn:micasaverde-com:serviceId:ZWaveNetwork1")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module MiOS
2
+ VERSION = "0.1.0"
3
+ end
data/lib/mios.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'httparty'
2
+ require "mios/version"
3
+ require "mios/interface"
4
+ require "mios/device"
5
+ require "mios/action"
6
+ require "mios/job"
7
+ Dir[File.dirname(__FILE__) + '/mios/services/*.rb'].each {|file| require file }
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
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+ require File.expand_path('spec_helper.rb', File.dirname(__FILE__))
3
+
4
+ describe "truth" do
5
+ it "trivial test" do
6
+ 1.should eq 1
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ require 'rubygems'
2
+ require 'rspec'
3
+
4
+ $LOAD_PATH << "#{File.expand_path(File.dirname(__FILE__))}/../lib"
5
+ require "mios"
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: