web_power_switch 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ *.swp
6
+ *~
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in web_power_switch.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Marketfish
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,8 @@
1
+ Web Power Switch
2
+ ================
3
+
4
+ Web Power Switch is a Ruby gem for viewing and managing ports of a Web Power
5
+ Switch III, built by Digital Loggers, Inc.
6
+
7
+ For more details on the hardware check the
8
+ [product page](http://www.digital-loggers.com/lpc.html).
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,3 @@
1
+ class WebPowerSwitch
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,85 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'nokogiri'
4
+
5
+ class WebPowerSwitch
6
+ class CommunicationError < StandardError
7
+ attr_reader :response
8
+ def initialize(response)
9
+ @response = response
10
+ end
11
+ end
12
+
13
+ class Outlet < Struct.new(:name, :number, :status); end
14
+
15
+ def initialize(address='192.168.0.100', port=80,
16
+ user='admin', password='1234', options={})
17
+ @address, @port, @user, @password = address, port, user, password
18
+ @options = options
19
+ end
20
+
21
+ def status
22
+ if @options[:cache_status]
23
+ @jacks ||= parse_socket_status geturl('/index.htm')
24
+ else
25
+ parse_socket_status geturl('/index.htm')
26
+ end
27
+ end
28
+
29
+ [:on, :off, :ccl].each do |method|
30
+ define_method(method) do |outlet|
31
+ if outlet = valid_outlet(outlet)
32
+ clear_status
33
+ response = geturl("/outlet?#{outlet}=#{method.to_s.upcase}")
34
+ else
35
+ raise ArgumentError, "Not a valid outlet"
36
+ end
37
+ end
38
+ end
39
+
40
+ private
41
+ def valid_outlet(outlet)
42
+ status if @jacks.nil? || @jacks.empty?
43
+ outlet_str = outlet.to_s.downcase
44
+ return outlet_str if outlet_str == "a"
45
+ return outlet.to_i if (1..8).include? outlet.to_i
46
+ if good_outlet = find_outlet(outlet)
47
+ return good_outlet.number
48
+ end
49
+ return false
50
+ end
51
+
52
+ def clear_status
53
+ @jacks = nil
54
+ end
55
+
56
+ def find_outlet(name)
57
+ @jacks.select {|j| j.name.downcase == name.downcase }.first
58
+ end
59
+
60
+ def parse_socket_status(response)
61
+ html = Nokogiri::HTML response.body
62
+ rows = html.css('table')[5].css('tr').slice(2, 8)
63
+
64
+ return rows.inject([]) do |jacks, row|
65
+ number, name, status = row.css('td').map {|t| t.text.strip }
66
+ outlet = Outlet.new(name, number.to_i, status.downcase.to_sym)
67
+ jacks << outlet
68
+ end
69
+ end
70
+
71
+ def geturl(page)
72
+ response = nil
73
+ Net::HTTP.start(@address, @port) do |http|
74
+ req = Net::HTTP::Get.new(page)
75
+ req.basic_auth @user, @password
76
+ response = http.request(req)
77
+ end
78
+
79
+ if response.class == Net::HTTPOK
80
+ return response
81
+ else
82
+ raise CommunicationError.new(response), "Could not talk to powerswitch: code #{response.code}"
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,233 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: <%= "http://#{user}:#{password}@#{address}:#{port}/index.htm" %>
6
+ body:
7
+ headers:
8
+ authorization:
9
+ - Basic YWRtaW46MTIzNA==
10
+ response: !ruby/struct:VCR::Response
11
+ status: !ruby/struct:VCR::ResponseStatus
12
+ code: 200
13
+ message: OK
14
+ headers:
15
+ content-type:
16
+ - text/html
17
+ cache control:
18
+ - No-store
19
+ expires:
20
+ - Mon, 06 Jan 1990 00:00:01 GMT
21
+ pragma:
22
+ - no-cache
23
+ set-cookie:
24
+ - DLILPC=""; Version=1; Max-Age=0; Path=/
25
+ body: |
26
+ <html>
27
+ <head>
28
+ <META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
29
+
30
+ <META HTTP-EQUIV="Refresh" CONTENT="300">
31
+ <title>Outlet Control - Web Power Switch III</title></head>
32
+ <!-- state=ff lock=00 -->
33
+
34
+ <body alink="#0000FF" vlink="#0000FF">
35
+ <FONT FACE="Arial, Helvetica, Sans-Serif">
36
+ <table width="100%" cellspacing=0 cellpadding=0>
37
+ <tr>
38
+ <td valign=top width="17%" height="100%">
39
+
40
+ <!-- menu -->
41
+ <table width="100%" height="100%" align=center border=0 cellspacing=1 cellpadding=0>
42
+ <tr><td valign=top bgcolor="#F4F4F4">
43
+ <table width="100%" cellpadding=1 cellspacing=5>
44
+
45
+ <tr><td align=center>
46
+
47
+ <table><tr><td><a href="http://www.digital-loggers.com/8.html"><img src=logo.gif width=195 height=65 border=0 alt="Digital Loggers, Inc"></a></td>
48
+
49
+ <td><b><font size=-1>Ethernet Power Controller</font></b></td></tr></table>
50
+ <hr>
51
+ </td></tr>
52
+
53
+
54
+
55
+ <tr><td nowrap><b><a href="/index.htm">Outlet Control</a></b></td></tr>
56
+ <tr><td nowrap><b><a href="/admin.htm">Setup</a></b></td></tr>
57
+ <tr><td nowrap><b><a href="/script.htm">Scripting</a></b></td></tr>
58
+
59
+
60
+
61
+
62
+
63
+ <tr><td nowrap><b><a href="/ap.htm">AutoPing</a></b></td></tr>
64
+ <tr><td nowrap><b><a href="/syslog.htm">System Log</a></b></td></tr>
65
+ <tr><td nowrap><b><a href="/logout">Logout</a></b></td></tr>
66
+ <tr><td nowrap><b><a href="/help/">Help</a></b></td></tr>
67
+
68
+ <tr><td><hr></td></tr>
69
+
70
+
71
+ <tr><td><b><a href="http://www.digital-loggers.com/5.html">Manual</a></b></td></tr>
72
+
73
+ <tr><td><b><a href="http://www.digital-loggers.com/6.html">FAQ</a></b></td></tr>
74
+
75
+ <tr><td><b><a href="http://www.digital-loggers.com/7.html">Product Information</a></b></td></tr>
76
+
77
+ <tr><td><b><a href="http://www.digital-loggers.com/8.html">Digital Loggers, Inc.</a></b></td></tr>
78
+
79
+
80
+ </table>
81
+ </td></tr>
82
+
83
+
84
+ <tr><td valign=bottom height="100%" bgcolor="#F4F4F4">
85
+ <small>Version 1.4.3 (Mar 14 2010 / 18:25:22) 8AA39795-B6EF1CE7</small>
86
+ </td></tr>
87
+ <tr><td valign=bottom height="100%" bgcolor="#F4F4F4">
88
+ <small>S/N:0000333967</small>
89
+ </td></tr>
90
+
91
+ </table>
92
+ <!-- /menu -->
93
+
94
+ </td>
95
+ <td valign=top width="83%">
96
+
97
+ <!-- heading table -->
98
+ <table width="100%" align=center border=0 cellspacing=1 cellpadding=3>
99
+ <tr><td bgcolor=red>&nbsp;</td></tr><tr><td align=center><h1>We recommend that you change the password!</h1></td></tr><tr><td bgcolor=red>&nbsp;</td></tr>
100
+ <tr>
101
+ <th bgcolor="#DDDDFF" align=left>
102
+ Controller: Web Power Switch III
103
+ </th>
104
+ </tr>
105
+
106
+ <tr bgcolor="#FFFFFF" align=left>
107
+ <td>
108
+ Uptime: 94:00:49 <!-- 338449s up -->
109
+ </td>
110
+ </tr>
111
+
112
+ </table>
113
+ <!-- /heading table -->
114
+
115
+ <br>
116
+
117
+ <!-- individual control table -->
118
+ <table width="100%" align=center border=0 cellspacing=1 cellpadding=3>
119
+
120
+ <tr>
121
+ <td bgcolor="#DDDDFF" colspan=5 align=left>
122
+ Individual Control
123
+ </td>
124
+ </tr>
125
+
126
+ <!-- heading rows -->
127
+ <tr bgcolor="#DDDDDD">
128
+ <th>#</th>
129
+ <th align=left>Name</th>
130
+ <th align=left>State</th>
131
+ <th align=left colspan=2>Action</th>
132
+ </tr>
133
+ <!-- /heading rows -->
134
+
135
+
136
+
137
+
138
+ <tr bgcolor="#F4F4F4"><td align=center>1</td>
139
+ <td>Outlet 1</td><td>
140
+ <b><font color=green>ON</font></b></td><td>
141
+ <a href=outlet?1=OFF>Switch OFF</a>
142
+ </td><td>
143
+ <a href=outlet?1=CCL>Cycle</a>
144
+ </td></tr>
145
+
146
+
147
+ <tr bgcolor="#F4F4F4"><td align=center>2</td>
148
+ <td>Outlet 2</td><td>
149
+ <b><font color=green>ON</font></b></td><td>
150
+ <a href=outlet?2=OFF>Switch OFF</a>
151
+ </td><td>
152
+ <a href=outlet?2=CCL>Cycle</a>
153
+ </td></tr>
154
+
155
+
156
+ <tr bgcolor="#F4F4F4"><td align=center>3</td>
157
+ <td>Outlet 3</td><td>
158
+ <b><font color=green>ON</font></b></td><td>
159
+ <a href=outlet?3=OFF>Switch OFF</a>
160
+ </td><td>
161
+ <a href=outlet?3=CCL>Cycle</a>
162
+ </td></tr>
163
+
164
+
165
+ <tr bgcolor="#F4F4F4"><td align=center>4</td>
166
+ <td>Outlet 4</td><td>
167
+ <b><font color=green>ON</font></b></td><td>
168
+ <a href=outlet?4=OFF>Switch OFF</a>
169
+ </td><td>
170
+ <a href=outlet?4=CCL>Cycle</a>
171
+ </td></tr>
172
+
173
+
174
+ <tr bgcolor="#F4F4F4"><td align=center>5</td>
175
+ <td>Outlet 5</td><td>
176
+ <b><font color=green>ON</font></b></td><td>
177
+ <a href=outlet?5=OFF>Switch OFF</a>
178
+ </td><td>
179
+ <a href=outlet?5=CCL>Cycle</a>
180
+ </td></tr>
181
+
182
+
183
+ <tr bgcolor="#F4F4F4"><td align=center>6</td>
184
+ <td>Outlet 6</td><td>
185
+ <b><font color=green>ON</font></b></td><td>
186
+ <a href=outlet?6=OFF>Switch OFF</a>
187
+ </td><td>
188
+ <a href=outlet?6=CCL>Cycle</a>
189
+ </td></tr>
190
+
191
+
192
+ <tr bgcolor="#F4F4F4"><td align=center>7</td>
193
+ <td>Outlet 7</td><td>
194
+ <b><font color=green>ON</font></b></td><td>
195
+ <a href=outlet?7=OFF>Switch OFF</a>
196
+ </td><td>
197
+ <a href=outlet?7=CCL>Cycle</a>
198
+ </td></tr>
199
+
200
+
201
+ <tr bgcolor="#F4F4F4"><td align=center>8</td>
202
+ <td>Outlet 8</td><td>
203
+ <b><font color=green>ON</font></b></td><td>
204
+ <a href=outlet?8=OFF>Switch OFF</a>
205
+ </td><td>
206
+ <a href=outlet?8=CCL>Cycle</a>
207
+ </td></tr>
208
+
209
+
210
+ </table>
211
+ <!-- /individual control table -->
212
+
213
+ <br>
214
+
215
+ <table width="100%" align=center border=0 cellspacing=1 cellpadding=3>
216
+ <tr><td bgcolor="#DDDDFF" align=left>Master Control</td></tr>
217
+
218
+ <tr><td bgcolor="#F4F4F4" align=left><a href=outlet?a=OFF>All outlets OFF</a></td></tr>
219
+ <tr><td bgcolor="#F4F4F4" align=left><a href=outlet?a=ON>All outlets ON</a></td></tr>
220
+ <tr><td bgcolor="#F4F4F4" align=left><a href=outlet?a=CCL>Cycle all outlets</a></td></tr>
221
+ <tr><td align=center>Sequence delay: 1 sec.</td></tr>
222
+
223
+ </table>
224
+
225
+
226
+ </td>
227
+ </tr>
228
+ </table>
229
+
230
+ </body>
231
+ </html>
232
+
233
+ http_version: "1.0"
@@ -0,0 +1,8 @@
1
+ require File.dirname(__FILE__) + '/../lib/web_power_switch'
2
+ require 'vcr'
3
+
4
+
5
+ VCR.config do |c|
6
+ c.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
7
+ c.stub_with :webmock
8
+ end
@@ -0,0 +1,36 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe WebPowerSwitch do
4
+ before(:each) do
5
+ @address = ENV['WPS_ADDRESS'] || 'localhost'
6
+ @port = ENV['WPS_PORT'] || '8080'
7
+ @user = ENV['WPS_USER'] || 'admin'
8
+ @password = ENV['WPS_PASSWORD'] || 'password'
9
+ end
10
+
11
+ it "should take a IP, port, user and password" do
12
+ wps = WebPowerSwitch.new(@address, @port, @user, @password)
13
+ end
14
+
15
+ it "should connect successfully to power supply" do
16
+ wps = WebPowerSwitch.new(@address, @port, @user, @password)
17
+ VCR.use_cassette('status',
18
+ :erb => { :address => @address, :port => @port, :user => @user, :password => @password },
19
+ :match_requests_on => [:uri, :method, :body] ) do
20
+ response = wps.status
21
+
22
+ end
23
+ end
24
+ context "#status" do
25
+ it "should returns a hash with each sockets current status" do
26
+ wps = WebPowerSwitch.new(@address, @port, @user, @password)
27
+ VCR.use_cassette('status',
28
+ :erb => { :address => @address, :port => @port, :user => @user, :password => @password },
29
+ :match_requests_on => [:uri, :method, :body] ) do
30
+ response = wps.status
31
+ expected = 8.times.inject([]) {|m,i| m << WebPowerSwitch::Outlet.new("Outlet #{i+1}", i+1, :on)}
32
+ response.should == expected
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "web_power_switch/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "web_power_switch"
7
+ s.version = WebPowerSwitch::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Kyle Burckhard"]
10
+ s.email = ["kyle@marketfish.com"]
11
+ s.homepage = ""
12
+ s.summary = %q{Controls a Web Power Supply by DLI}
13
+ s.description = %q{API and binary to control ports and check status of a Web Power Supply from Data Loggers Inc.}
14
+
15
+ s.rubyforge_project = "web_power_switch"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency 'nokogiri'
23
+ s.add_development_dependency 'rspec', '>2.0.0'
24
+ s.add_development_dependency 'vcr', '~>1.10.0'
25
+ s.add_development_dependency 'webmock'
26
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: web_power_switch
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Kyle Burckhard
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-06-03 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: nokogiri
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: rspec
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">"
33
+ - !ruby/object:Gem::Version
34
+ version: 2.0.0
35
+ type: :development
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: vcr
39
+ prerelease: false
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.10.0
46
+ type: :development
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: webmock
50
+ prerelease: false
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ type: :development
58
+ version_requirements: *id004
59
+ description: API and binary to control ports and check status of a Web Power Supply from Data Loggers Inc.
60
+ email:
61
+ - kyle@marketfish.com
62
+ executables: []
63
+
64
+ extensions: []
65
+
66
+ extra_rdoc_files: []
67
+
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - LICENSE
72
+ - README.md
73
+ - Rakefile
74
+ - lib/web_power_switch.rb
75
+ - lib/web_power_switch/version.rb
76
+ - spec/fixtures/vcr_cassettes/status.yml
77
+ - spec/spec_helper.rb
78
+ - spec/web_power_switch_spec.rb
79
+ - web_power_switch.gemspec
80
+ homepage: ""
81
+ licenses: []
82
+
83
+ post_install_message:
84
+ rdoc_options: []
85
+
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: "0"
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: "0"
100
+ requirements: []
101
+
102
+ rubyforge_project: web_power_switch
103
+ rubygems_version: 1.7.2
104
+ signing_key:
105
+ specification_version: 3
106
+ summary: Controls a Web Power Supply by DLI
107
+ test_files:
108
+ - spec/fixtures/vcr_cassettes/status.yml
109
+ - spec/spec_helper.rb
110
+ - spec/web_power_switch_spec.rb