wemote 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8fab169b7fb29b3ed90820cfa268951f6a88f28d
4
- data.tar.gz: cd0c3fd1971486865e170eae94cca933e1558070
3
+ metadata.gz: 50907f96c202b14aff7fbac722c9133a3c4860f5
4
+ data.tar.gz: 2fa839d4ce9819d5223f078b08464906556bcfb1
5
5
  SHA512:
6
- metadata.gz: f365c6b952fd03d3b38d53081ede3d21ac1d28a1c4568e0d0275d9f3ddc0732a0b8651fbf33a20c0aa43d9335b0d41449906df90f4902e74a064f2f08e304de1
7
- data.tar.gz: aafdae13551a09dfc8b4ce12336e6a3e3971add9667f7a61c5dd4b57353e5d49e4f69112d0a6945304852e00320d33ef89a2d3029006ae3decd2e42c053274e6
6
+ metadata.gz: 352264a9e37d2d4e3e54e1925b751e2d37adb277cfd7e6b818864afd3315fa0f332bd836242f5d2f7e8c1fecc6571761c214eac4126c9c6f1143e37236a8047f
7
+ data.tar.gz: c7a62b670905ff95356342c2886d76f61cc21e2384c0da60abff32fea4fb267b503faa7ac8482d208fb66151cf5e91ebf9523a6f2aac787addde5a39c3769c1e
@@ -2,7 +2,9 @@ require_relative './wemote/version'
2
2
 
3
3
  module Wemote
4
4
  require_relative './wemote/collection/switch'
5
+ require_relative './wemote/collection/insight'
5
6
  require_relative './wemote/switch'
7
+ require_relative './wemote/insight'
6
8
  require_relative './wemote/client'
7
9
  require_relative './wemote/xml'
8
10
 
@@ -0,0 +1,12 @@
1
+ module Wemote
2
+ module Collection
3
+
4
+ # This class provides an extension on the basic Array object, in order to
5
+ # facilitate group operations on a collection of Wemote::Switch instances.
6
+ class Insight < Switch
7
+
8
+ make :standby?
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,90 @@
1
+ require 'socket'
2
+ require 'ipaddr'
3
+ require 'timeout'
4
+ require 'ssdp'
5
+
6
+ module Wemote
7
+
8
+ # This class encapsulates an individual Wemo Insight. It provides methods for
9
+ # getting and setting the insight's state, as well as a {#toggle!} method for
10
+ # convenience. Finally, it provides the {#poll} method, which accepts a block
11
+ # to be executed any time the insight changes state.
12
+ class Insight < Switch
13
+
14
+ GET_HEADERS_POWER = {
15
+ "SOAPACTION" => '"urn:Belkin:service:insight:1#GetInsightParams"',
16
+ "Content-type" => 'text/xml; charset="utf-8"'
17
+ }
18
+
19
+ class << self
20
+
21
+ def device_type
22
+ 'urn:Belkin:device:insight:1'
23
+ end
24
+
25
+ # Returns all Insight detected on the local network
26
+ #
27
+ # @param [Boolean] refresh Refresh and redetect Insight
28
+ # @return [Array] all Insight on the network
29
+ def all(refresh=false)
30
+ @insights = nil if refresh
31
+ @insights ||= Wemote::Collection::Insight.new(discover)
32
+ end
33
+
34
+ end
35
+
36
+ # Turn the Insight on or off, based on its current state
37
+ def toggle!
38
+ on? or standby? ? off! : on!;
39
+ end
40
+
41
+ # Return whether the Insight is standby
42
+ #
43
+ # @return [Boolean]
44
+ def standby?
45
+ get_state == :standby;
46
+ end
47
+
48
+ def power
49
+ get_insight_params()[:power]
50
+ end
51
+
52
+ def energy
53
+ get_insight_params()[:energy]
54
+ end
55
+
56
+ def on_today
57
+ get_insight_params()[:on_today]
58
+ end
59
+
60
+ private
61
+
62
+ def get_state
63
+ case get_binary_state()
64
+ when '0'
65
+ :off
66
+ when '1'
67
+ :on
68
+ when '8'
69
+ :standby
70
+ end
71
+ end
72
+
73
+ def get_insight_params
74
+ response = begin
75
+ client.post("http://#{@host}:#{@port}/upnp/control/insight1",Wemote::XML.get_insight_params,GET_HEADERS_POWER)
76
+ rescue Exception
77
+ client.post("http://#{@host}:#{@port}/upnp/control/insight1",Wemote::XML.get_insight_params,GET_HEADERS_POWER)
78
+ end
79
+ params = response.body.match(/<InsightParams>(.*)<\/InsightParams>/)[1].split('|')
80
+ {
81
+ value: (params[0].to_i == 0 ? :off : :on),
82
+ energy: (params[8].to_i / 60000000.0).ceil,
83
+ power: (params[7].to_i / 1000.0).round,
84
+ on_today: (params[3].to_i / 60.0).floor
85
+ }
86
+ end
87
+
88
+
89
+ end
90
+ end
@@ -1,6 +1,7 @@
1
1
  require 'socket'
2
2
  require 'ipaddr'
3
3
  require 'timeout'
4
+ require 'ssdp'
4
5
 
5
6
  module Wemote
6
7
 
@@ -10,8 +11,6 @@ module Wemote
10
11
  # to be executed any time the switch changes state.
11
12
  class Switch
12
13
 
13
- GOOGLE_IP = "64.233.187.99"
14
-
15
14
  GET_HEADERS = {
16
15
  "SOAPACTION" => '"urn:Belkin:service:basicevent:1#GetBinaryState"',
17
16
  "Content-type" => 'text/xml; charset="utf-8"'
@@ -23,6 +22,11 @@ module Wemote
23
22
  }
24
23
 
25
24
  class << self
25
+
26
+ def device_type
27
+ 'urn:Belkin:device:controllee:1'
28
+ end
29
+
26
30
  # Returns all Switches detected on the local network
27
31
  #
28
32
  # @param [Boolean] refresh Refresh and redetect Switches
@@ -40,14 +44,15 @@ module Wemote
40
44
  all.detect{|s|s.name == name}
41
45
  end
42
46
 
43
- private
47
+ protected
44
48
 
45
49
  def discover
46
- ip = UDPSocket.open {|s| s.connect(GOOGLE_IP, 1); s.addr.last}
47
- `nmap -sP #{ip.split('.')[0..-2].join('.')}.* > /dev/null && arp -na | grep b4:75`.split("\n").map do |device|
48
- self.new(/\((\d+\.\d+\.\d+\.\d+)\)/.match(device)[1])
49
- end.reject{|device| device.instance_variable_get(:@port).nil? }
50
+ finder = SSDP::Consumer.new timeout: 3, first_only: false
51
+ finder.search(service: self.device_type).map do |device|
52
+ self.new(device[:address], device[:params]['LOCATION'].match(/:([0-9]{1,5})\//)[1])
53
+ end
50
54
  end
55
+
51
56
  end
52
57
 
53
58
  attr_accessor :name
@@ -57,24 +62,38 @@ module Wemote
57
62
  set_meta
58
63
  end
59
64
 
65
+ def device_type
66
+ 'urn:Belkin:device:controllee:1'
67
+ end
68
+
60
69
  # Turn the Switch on or off, based on its current state
61
- def toggle!; on? ? off! : on!; end
70
+ def toggle!
71
+ on? ? off! : on!
72
+ end
62
73
 
63
74
  # Turn the Switch off
64
- def off!; set_state(0); end
75
+ def off!
76
+ set_state(0)
77
+ end
65
78
 
66
79
  # Turn the Switch on
67
- def on!; set_state(1); end
80
+ def on!
81
+ set_state(1)
82
+ end
68
83
 
69
84
  # Return whether the Switch is off
70
85
  #
71
86
  # @return [Boolean]
72
- def off?; get_state == :off; end
87
+ def off?
88
+ get_state == :off
89
+ end
73
90
 
74
91
  # Return whether the Switch is on
75
92
  #
76
93
  # @return [Boolean]
77
- def on?; get_state == :on; end
94
+ def on?
95
+ get_state == :on
96
+ end
78
97
 
79
98
  # Monitors the state of the Switch via polling, and yields to the block
80
99
  # given with the updated state.
@@ -111,15 +130,19 @@ module Wemote
111
130
  async ? poller : poller.join
112
131
  end
113
132
 
114
- private
133
+ protected
115
134
 
116
135
  def get_state
136
+ self.get_binary_state() == '1' ? :on : :off
137
+ end
138
+
139
+ def get_binary_state
117
140
  response = begin
118
141
  client.post("http://#{@host}:#{@port}/upnp/control/basicevent1",Wemote::XML.get_binary_state,GET_HEADERS)
119
142
  rescue Exception
120
143
  client.post("http://#{@host}:#{@port}/upnp/control/basicevent1",Wemote::XML.get_binary_state,GET_HEADERS)
121
144
  end
122
- response.body.match(/<BinaryState>(\d)<\/BinaryState>/)[1] == '1' ? :on : :off
145
+ response.body.match(/<BinaryState>(\d)<\/BinaryState>/)[1]
123
146
  end
124
147
 
125
148
  def set_state(state)
@@ -135,22 +158,8 @@ module Wemote
135
158
  end
136
159
 
137
160
  def set_meta
138
- if @port
139
- response = client.get("http://#{@host}:#{@port}/setup.xml")
140
- @name = response.body.match(/<friendlyName>([^<]+)<\/friendlyName>/)[1]
141
- else
142
- for port in 49152..49156
143
- begin
144
- response = nil
145
- Timeout::timeout(1){ response = client.get("http://#{@host}:#{port}/setup.xml") }
146
- @name = response.body.match(/<friendlyName>([^<]+)<\/friendlyName>/)[1]
147
- @port = port
148
- break
149
- rescue Exception
150
- end
151
- end
152
- end
161
+ response = client.get("http://#{@host}:#{@port}/setup.xml")
162
+ @name = response.body.match(/<friendlyName>([^<]+)<\/friendlyName>/)[1]
153
163
  end
154
-
155
164
  end
156
165
  end
@@ -1,3 +1,3 @@
1
1
  module Wemote
2
- VERSION = "0.2.2"
2
+ VERSION = "0.2.3"
3
3
  end
@@ -4,7 +4,8 @@ module Wemote
4
4
  xml_path = File.join(File.dirname(__FILE__),'/../../xml')
5
5
  TEMPLATES = {
6
6
  get_binary_state: File.read(File.join(xml_path,'get_binary_state.xml')),
7
- set_binary_state: File.read(File.join(xml_path,'set_binary_state.xml'))
7
+ set_binary_state: File.read(File.join(xml_path,'set_binary_state.xml')),
8
+ get_insight_params: File.read(File.join(xml_path,'get_insight_params.xml'))
8
9
  }
9
10
 
10
11
  # @return [String] The required XML body for a Wemo binary state request
@@ -18,6 +19,11 @@ module Wemote
18
19
  TEMPLATES[:set_binary_state].gsub("{{1}}",state.to_s)
19
20
  end
20
21
 
22
+ def get_insight_params
23
+ TEMPLATES[:get_insight_params]
24
+ end
25
+
26
+
21
27
  end
22
28
  end
23
29
  end
@@ -18,4 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
20
  spec.require_paths = ["lib"]
21
+
22
+ spec.add_dependency 'ssdp', '~> 1.1', '>= 1.1.6'
23
+
21
24
  end
@@ -1,6 +1,5 @@
1
1
  <?xml version="1.0" encoding="utf-8"?>
2
- <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
3
- s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
2
+ <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
4
3
  <s:Body>
5
4
  <u:GetBinaryState xmlns:u="urn:Belkin:service:basicevent:1"/>
6
5
  </s:Body>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
3
+ <s:Body>
4
+ <u:GetInsightParams xmlns:u="urn:Belkin:service:insight:1"></u:GetInsightParams>
5
+ </s:Body>
6
+ </s:Envelope>
@@ -1,6 +1,5 @@
1
1
  <?xml version="1.0" encoding="utf-8"?>
2
- <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
3
- s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
2
+ <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
4
3
  <s:Body>
5
4
  <u:SetBinaryState xmlns:u="urn:Belkin:service:basicevent:1">
6
5
  <BinaryState>{{1}}</BinaryState>
metadata CHANGED
@@ -1,15 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wemote
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Gisi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-08 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2018-03-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ssdp
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.1'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.1.6
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.1'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.1.6
13
33
  description: Wemote is a Ruby-agnostic gem for Wemo light switches
14
34
  email:
15
35
  - kevin@kevingisi.com
@@ -25,7 +45,9 @@ files:
25
45
  - Rakefile
26
46
  - lib/wemote.rb
27
47
  - lib/wemote/client.rb
48
+ - lib/wemote/collection/insight.rb
28
49
  - lib/wemote/collection/switch.rb
50
+ - lib/wemote/insight.rb
29
51
  - lib/wemote/switch.rb
30
52
  - lib/wemote/version.rb
31
53
  - lib/wemote/xml.rb
@@ -33,6 +55,7 @@ files:
33
55
  - spec/wemote/switch_spec.rb
34
56
  - wemote.gemspec
35
57
  - xml/get_binary_state.xml
58
+ - xml/get_insight_params.xml
36
59
  - xml/set_binary_state.xml
37
60
  homepage: https://github.com/gisikw/wemote
38
61
  licenses:
@@ -54,11 +77,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
54
77
  version: '0'
55
78
  requirements: []
56
79
  rubyforge_project:
57
- rubygems_version: 2.2.2
80
+ rubygems_version: 2.6.14
58
81
  signing_key:
59
82
  specification_version: 4
60
83
  summary: Wemote is a Ruby-agnostic gem for Wemo light switches
61
84
  test_files:
62
85
  - spec/spec_helper.rb
63
86
  - spec/wemote/switch_spec.rb
64
- has_rdoc: