powercontroller9202 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gemtest +0 -0
- data/History.txt +3 -0
- data/Manifest.txt +6 -0
- data/README.txt +139 -0
- data/Rakefile +11 -0
- data/lib/powercontroller9202.rb +382 -0
- data/test/test.rb +56 -0
- metadata +90 -0
data/.gemtest
ADDED
File without changes
|
data/History.txt
ADDED
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
= powercontroller9202
|
2
|
+
|
3
|
+
* https://github.com/rbur004/powercontroller9202
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
A Ruby GEDCOM to communicate with an Aviosys Inc. 9202 IP Power Controller (and associated products (eg 9212)).
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
* see the status of the relays
|
12
|
+
* turns relays on and off without altering the saved state on power up
|
13
|
+
* turns relays on and off, and alters the saved state for next power up
|
14
|
+
* Toggles any or all relays
|
15
|
+
|
16
|
+
== SYNOPSIS:
|
17
|
+
|
18
|
+
require 'powercontroller9202'
|
19
|
+
|
20
|
+
#Default to relay off state being a power on state
|
21
|
+
pc = PowerController9202.new("192.168.249.128", "admin", "xxxxx")
|
22
|
+
|
23
|
+
#change so relay off state is a power off state
|
24
|
+
#pc = PowerController9202.new("192.168.249.128", "admin", "xxxxxx", false)
|
25
|
+
|
26
|
+
#8 relays, not 4
|
27
|
+
#relay off state is a power on state
|
28
|
+
#pc = PowerController9202.new("192.168.249.128", "admin", "xxxxxx", true, 8)
|
29
|
+
|
30
|
+
#Manually set the portmap. Nb portmap[0] is unused.
|
31
|
+
#pc = PowerController9202.new("192.168.249.128", "admin", "xxxxxx")
|
32
|
+
#pc.portmap = [0,0,2,5,7,1,3,4,6]
|
33
|
+
#pc.set_status #to update the status bitmap
|
34
|
+
|
35
|
+
|
36
|
+
puts pc.status.to_s #current relay states as array of 0's and 1's for relay off and on
|
37
|
+
puts pc.to_s(['server', 'modem', 'lights', 'tv']) #outputs relay status with names.
|
38
|
+
puts pc #Prints the relay status (Equivalent to puts pc.to_s )
|
39
|
+
|
40
|
+
exit #currently testing against an installed controller , as the test version failed.
|
41
|
+
|
42
|
+
#Power on means the relay switch the power on, even if the relay power is off
|
43
|
+
#Relay on, means the relay is powered, but that might mean the power is then off.
|
44
|
+
pc.ensureon #Turns all relays to the power on state (not saved)
|
45
|
+
pc.off([2,4]) #Turns relays 2 and 4 power off (not saved)
|
46
|
+
pc.on([2,4]) #Turns relays 2 and 4 power on (not saved)
|
47
|
+
|
48
|
+
|
49
|
+
pg.toggle_all #Turns power off for 5 seconds through all relays (understands my off is on)
|
50
|
+
pg.toggle_all(10) #Turns power on for 10 seconds through all relays (understands my off is on)
|
51
|
+
|
52
|
+
|
53
|
+
pc.toggle(1) #Turns power off for 5 seconds through relay 1(understands my off is on).
|
54
|
+
pc.toggle(1,10) #Turns power off for 10 seconds through relay 1 (understands my off is on)
|
55
|
+
|
56
|
+
pc.toggle([1,4]) #Turns power off for 5 seconds through relay 1 & 4 (understands my off is on)
|
57
|
+
pc.toggle([2,3],10) #Turns power off for 10 seconds through relays 2 & 3 (understands my off is on).
|
58
|
+
|
59
|
+
#Via the web form, rather thon SetIO
|
60
|
+
pc.reset_all #Sets relays to off state (Relays off, not necessarily power off)
|
61
|
+
#For mine, that is an on state as I want the failure state to be on
|
62
|
+
#The web interface shows them as off though.
|
63
|
+
|
64
|
+
#Via the web form, rather thon SetIO
|
65
|
+
pc.timer_toggle_all #Turns off the relays, then on again after 5 seconds
|
66
|
+
pc.timer_toggle_all(10) #Turns off the relays, then on again after 10 seconds
|
67
|
+
|
68
|
+
#Via the web form, rather thon SetIO
|
69
|
+
pc.on2(3) #Turns relay 3 power on and it shows up that way in the web interface.
|
70
|
+
#Hence will be set this way after the 9202 is power cycled.
|
71
|
+
pc.off2(2) #Turns relay 2 power off and it shows up that way in the web interface.
|
72
|
+
#Hence will be set this way after the 9202 is power cycled.
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
== REQUIREMENTS:
|
77
|
+
|
78
|
+
* require 'rubygems'
|
79
|
+
* require 'powercontroller9202'
|
80
|
+
|
81
|
+
== INSTALL:
|
82
|
+
|
83
|
+
* sudo gem install powercontroller9202
|
84
|
+
|
85
|
+
== LICENSE:
|
86
|
+
|
87
|
+
Distributed under the Ruby License.
|
88
|
+
|
89
|
+
Copyright (c) 2009
|
90
|
+
|
91
|
+
1. You may make and give away verbatim copies of the source form of the
|
92
|
+
software without restriction, provided that you duplicate all of the
|
93
|
+
original copyright notices and associated disclaimers.
|
94
|
+
|
95
|
+
2. You may modify your copy of the software in any way, provided that
|
96
|
+
you do at least ONE of the following:
|
97
|
+
|
98
|
+
a) place your modifications in the Public Domain or otherwise
|
99
|
+
make them Freely Available, such as by posting said
|
100
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
101
|
+
the author to include your modifications in the software.
|
102
|
+
|
103
|
+
b) use the modified software only within your corporation or
|
104
|
+
organization.
|
105
|
+
|
106
|
+
c) rename any non-standard executables so the names do not conflict
|
107
|
+
with standard executables, which must also be provided.
|
108
|
+
|
109
|
+
d) make other distribution arrangements with the author.
|
110
|
+
|
111
|
+
3. You may distribute the software in object code or executable
|
112
|
+
form, provided that you do at least ONE of the following:
|
113
|
+
|
114
|
+
a) distribute the executables and library files of the software,
|
115
|
+
together with instructions (in the manual page or equivalent)
|
116
|
+
on where to get the original distribution.
|
117
|
+
|
118
|
+
b) accompany the distribution with the machine-readable source of
|
119
|
+
the software.
|
120
|
+
|
121
|
+
c) give non-standard executables non-standard names, with
|
122
|
+
instructions on where to get the original software distribution.
|
123
|
+
|
124
|
+
d) make other distribution arrangements with the author.
|
125
|
+
|
126
|
+
4. You may modify and include the part of the software into any other
|
127
|
+
software (possibly commercial). But some files in the distribution
|
128
|
+
may not have been written by the author, so that they are not under this terms.
|
129
|
+
|
130
|
+
5. The scripts and library files supplied as input to or produced as
|
131
|
+
output from the software do not automatically fall under the
|
132
|
+
copyright of the software, but belong to whomever generated them,
|
133
|
+
and may be sold commercially, and may be aggregated with this
|
134
|
+
software.
|
135
|
+
|
136
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
137
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
138
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
139
|
+
PURPOSE.
|
data/Rakefile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
|
6
|
+
Hoe.spec 'powercontroller9202' do
|
7
|
+
self.rubyforge_name = 'powercontroller9202'
|
8
|
+
developer 'Rob Burrowes', 'r.burrowes@auckland.ac.nz'
|
9
|
+
remote_rdoc_dir = '' # Release to root
|
10
|
+
#extra_deps << 'whatevs'
|
11
|
+
end
|
@@ -0,0 +1,382 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require 'uri'
|
3
|
+
require 'digest/md5'
|
4
|
+
require 'scanf'
|
5
|
+
|
6
|
+
#Extention to the Array class to extend Array in a cleaner manner.
|
7
|
+
class PowerController9202Array < Array
|
8
|
+
#Add the seed value to the enumerated array values
|
9
|
+
def inject_with_index(seed=nil)
|
10
|
+
if seed == nil
|
11
|
+
seed = self[0]
|
12
|
+
start = 1
|
13
|
+
else
|
14
|
+
start = 0
|
15
|
+
end
|
16
|
+
self[start..-1].each_with_index do |a,i|
|
17
|
+
seed = yield(seed,a,i)
|
18
|
+
end
|
19
|
+
return seed
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
#Aviosys Inc. 9202 IP Power Controller
|
24
|
+
#PowerController provides a ruby API to the web interface
|
25
|
+
#
|
26
|
+
|
27
|
+
class PowerController9202
|
28
|
+
VERSION = '1.0.2'
|
29
|
+
|
30
|
+
attr_accessor :host #Hostname or IP address of the power controller
|
31
|
+
attr_accessor :user #username to login as (admin)
|
32
|
+
attr_accessor :portmap #Defoults to 4 relay version, can be set to 8 relay version, or manually set through this accessor.
|
33
|
+
attr_reader :status #The relay state. Set this with #set_status if you manually change portmap.
|
34
|
+
attr_writer :password
|
35
|
+
|
36
|
+
PORTMAP4 = [0,0,2,5,7] #The 4 relay version of the 9202 (my two are like this)
|
37
|
+
PORTMAP8 = [0,0,1,2,3,4,5,6,7,8] #The 8 relay version of the 9212
|
38
|
+
RELAY_ON = 1
|
39
|
+
RELAY_OFF = 0
|
40
|
+
|
41
|
+
#PowerController.new saves the hostname, username and password and returns the instantiated class
|
42
|
+
# on_is_off means the relays conduct power in their off state.
|
43
|
+
# My default is to use the relay off state as power on
|
44
|
+
# and the relay on state as the power being off (just a wiring decision)
|
45
|
+
# This means that a powercontroller failure will leave the devices on,
|
46
|
+
# which is what I want.
|
47
|
+
# portmap maps the relay number to the web interface's numbering (position on the board)
|
48
|
+
# I have only have 4 relays installed and they are on Port 0, 2, 5 and 7
|
49
|
+
# Numbering for SetIO & GetIO use 1,2,3 and 4 as relay numbers,
|
50
|
+
# but the web uses the actual relay position on the board.
|
51
|
+
# PORTMAP maps 1..4 to the actual ports for the web interfaces commands,
|
52
|
+
# so Array index 0 is unused
|
53
|
+
|
54
|
+
def initialize(host, user, password, on_is_off=true, portmap=4 )
|
55
|
+
@host = host
|
56
|
+
@user = user
|
57
|
+
@password = password
|
58
|
+
@power_on = on_is_off ? RELAY_OFF : RELAY_ON
|
59
|
+
@power_off = on_is_off ? RELAY_ON : RELAY_OFF
|
60
|
+
@portmap = portmap == 4 ? PORTMAP4 : PORTMAP8
|
61
|
+
set_status
|
62
|
+
end
|
63
|
+
|
64
|
+
#Fetches the relay states and return as an array of 1's and 0's
|
65
|
+
#1 means the relay is powered (though you might be using the relay off state as power on)
|
66
|
+
#0 means the relay is unpowered (though you might be using the relay off state as power on)
|
67
|
+
def set_status
|
68
|
+
Net::HTTP.start(@host) do |http|
|
69
|
+
response = http.get("/GetP6?")
|
70
|
+
if response.code.to_i == 200
|
71
|
+
#print response.body
|
72
|
+
@status = PowerController9202Array.new(response.body.scanf("<html>P61=%d,P62=%d,P63=%d,P64=%d</html>"))
|
73
|
+
else
|
74
|
+
#print "Connection failed with error #{response.code}\n"
|
75
|
+
raise "Connection failed with error #{response.code}\n"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
#'on' is short hand for tmp_change_state(outlet, @power_on)
|
82
|
+
#Using SetIO. Note that changes are lost after power cycle.
|
83
|
+
def on(outlet)
|
84
|
+
tmp_change_state(outlet, @power_on)
|
85
|
+
end
|
86
|
+
|
87
|
+
#'on' is short hand for tmp_change_state(outlet, @power_off)
|
88
|
+
#Using SetIO. Note that changes are lost after power cycle.
|
89
|
+
def off(outlet)
|
90
|
+
tmp_change_state(outlet, @power_off)
|
91
|
+
end
|
92
|
+
|
93
|
+
#Ensure_on will fetch each relays state, and turn the relay on, if it is off.
|
94
|
+
#Using SetIO. Note that changes are lost after power cycle.
|
95
|
+
def ensure_on
|
96
|
+
outlet = []
|
97
|
+
@status.each_with_index do |o,i|
|
98
|
+
if o == @power_off
|
99
|
+
outlet << i + 1
|
100
|
+
end
|
101
|
+
end
|
102
|
+
if outlet.length > 0 #We have relays to alter the state of
|
103
|
+
on(outlet)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
#toggle turns a relay off, then back on again, so the device is power cycled.
|
108
|
+
#If the outlet argument is an array, all relays specified in the array are power cycled.
|
109
|
+
#The time the relay is off is defined by the argument sleep_time (defoult of 5 seconds)
|
110
|
+
def toggle(outlet, sleep_time=5)
|
111
|
+
off(outlet)
|
112
|
+
sleep sleep_time
|
113
|
+
on(outlet)
|
114
|
+
end
|
115
|
+
|
116
|
+
#Toggle_all power cycles all the relays.
|
117
|
+
#The time the relay is off is defined by the argument sleep_time (defoult of 5 seconds)
|
118
|
+
def toggle_all(sleep_time=5)
|
119
|
+
outlet = []
|
120
|
+
@portmap[1..-1].each_with_index { |x,i| outlet << i+1 }
|
121
|
+
toggle(outlet, sleep_time)
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
#Reset_all uses the web form reset of each relays to the OFF state
|
126
|
+
#This persists after a device reboot, where the earlier calls do not.
|
127
|
+
def reset_all
|
128
|
+
login
|
129
|
+
res = Net::HTTP.new(@host, 80).start do |http|
|
130
|
+
|
131
|
+
post = Net::HTTP::Post.new('/tgi/ioControl.tgi')
|
132
|
+
#setting post body this way, as set_form_data randomised the order and device expects fixed order.
|
133
|
+
post.body = "PinNo=P6_0&P60=Off&P60_TIMER=0&P60_TIMER_CNTL=Off&" +
|
134
|
+
"PinNo=P6_1&P61=Off&P61_TIMER=0&P61_TIMER_CNTL=Off&" +
|
135
|
+
"PinNo=P6_2&P62=Off&P62_TIMER=0&P62_TIMER_CNTL=Off&" +
|
136
|
+
"PinNo=P6_3&P63=Off&P63_TIMER=0&P63_TIMER_CNTL=Off&" +
|
137
|
+
"PinNo=P6_4&P64=Off&P64_TIMER=0&P64_TIMER_CNTL=Off&" +
|
138
|
+
"PinNo=P6_5&P65=Off&P65_TIMER=0&P65_TIMER_CNTL=Off&" +
|
139
|
+
"PinNo=P6_6&P66=Off&P66_TIMER=0&P66_TIMER_CNTL=Off&" +
|
140
|
+
"PinNo=P6_7&P67=Off&P67_TIMER=0&P67_TIMER_CNTL=Off&" +
|
141
|
+
"Reset=Reset"
|
142
|
+
headers = {
|
143
|
+
'User-Agent' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9) Gecko/2008051206 Firefox/3.0',
|
144
|
+
'Content-Type' => 'application/x-www-form-urlencoded',
|
145
|
+
'Referer' => "http://#{@host}/ioControl_2e.htm",
|
146
|
+
'Cookie' => @cookie
|
147
|
+
}
|
148
|
+
|
149
|
+
response = http.post('/tgi/ioControl.tgi', post.body, headers)
|
150
|
+
if(response.code.to_i == 200)
|
151
|
+
@status.collect! { |v| 0 }
|
152
|
+
end
|
153
|
+
#puts response.code
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
#timer_toggle_all calls the web form to turn off the relays for the time period
|
158
|
+
#The earlier toggle uses the SetIO call, with an, OFF, sleep, then ON call.
|
159
|
+
def timer_toggle_all(sleep_time=5)
|
160
|
+
login
|
161
|
+
p6 = ["On","On","On","On","On","On","On","On"]
|
162
|
+
p6_time = ["0", "0", "0", "0","0","0","0","0"]
|
163
|
+
p6_timer = ["On","On","On","On","On","On","On","On"]
|
164
|
+
@portmap[1..-1].each do |pm|
|
165
|
+
p6[pm] = @power_on == "Off"
|
166
|
+
p6_time[pm] = "#{sleep_time}"
|
167
|
+
end
|
168
|
+
|
169
|
+
res = Net::HTTP.new(@host, 80).start do |http|
|
170
|
+
|
171
|
+
post = Net::HTTP::Post.new('/tgi/ioControl.tgi')
|
172
|
+
post.body = "PinNo=P6_0&P60=#{p6[0]}&P60_TIMER=#{p6_time[0]}&P60_TIMER_CNTL=#{p6_timer[0]}" +
|
173
|
+
"&PinNo=P6_1&P61=#{p6[1]}&P61_TIMER=#{p6_time[1]}&P61_TIMER_CNTL=#{p6_timer[1]}" +
|
174
|
+
"&PinNo=P6_2&P62=#{p6[2]}&P62_TIMER=#{p6_time[2]}&P62_TIMER_CNTL=#{p6_timer[2]}" +
|
175
|
+
"&PinNo=P6_3&P63=#{p6[3]}&P63_TIMER=#{p6_time[3]}&P63_TIMER_CNTL=#{p6_timer[3]}" +
|
176
|
+
"&PinNo=P6_4&P64=#{p6[4]}&P64_TIMER=#{p6_time[4]}&P64_TIMER_CNTL=#{p6_timer[4]}" +
|
177
|
+
"&PinNo=P6_5&P65=#{p6[5]}&P65_TIMER=#{p6_time[5]}&P65_TIMER_CNTL=#{p6_timer[5]}" +
|
178
|
+
"&PinNo=P6_6&P66=#{p6[6]}&P66_TIMER=#{p6_time[6]}&P66_TIMER_CNTL=#{p6_timer[6]}" +
|
179
|
+
"&PinNo=P6_7&P67=#{p6[7]}&P67_TIMER=#{p6_time[7]}&P67_TIMER_CNTL=#{p6_timer[7]}" +
|
180
|
+
"&Apply=Apply"
|
181
|
+
# print post.body
|
182
|
+
|
183
|
+
headers = {
|
184
|
+
'User-Agent' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9) Gecko/2008051206 Firefox/3.0',
|
185
|
+
'Content-Type' => 'application/x-www-form-urlencoded',
|
186
|
+
'Referer' => "http://#{@host}/ioControl_2e.htm",
|
187
|
+
'Cookie' => @cookie
|
188
|
+
}
|
189
|
+
|
190
|
+
response = http.post('/tgi/ioControl.tgi', post.body, headers)
|
191
|
+
#puts response.code
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
|
196
|
+
#Timer_toggle uses the web interface's power cycling feature.
|
197
|
+
#
|
198
|
+
#I only have 4 relays installed and they are on Port 0, 2, 5 and 7
|
199
|
+
#Numbering for SetIO & GetIO use 1,2,3 and 4 as relay numbers
|
200
|
+
def timer_toggle(outlet, sleep_time=5) #
|
201
|
+
login
|
202
|
+
|
203
|
+
p6 = ["On","On","On","On","On","On","On","On"]
|
204
|
+
p6_time = ["0", "0", "0", "0","0","0","0","0"]
|
205
|
+
p6_timer = ["On","On","On","On","On","On","On","On"]
|
206
|
+
p6[@portmap[outlet]] = "Off"
|
207
|
+
p6_time[@portmap[outlet]] = "#{sleep_time}"
|
208
|
+
|
209
|
+
res = Net::HTTP.new(@host, 80).start do |http|
|
210
|
+
|
211
|
+
post = Net::HTTP::Post.new('/tgi/ioControl.tgi')
|
212
|
+
post.body = "PinNo=P6_0&P60=#{p6[0]}&P60_TIMER=#{p6_time[0]}&P60_TIMER_CNTL=#{p6_timer[0]}" +
|
213
|
+
"&PinNo=P6_1&P61=#{p6[1]}&P61_TIMER=#{p6_time[1]}&P61_TIMER_CNTL=#{p6_timer[1]}" +
|
214
|
+
"&PinNo=P6_2&P62=#{p6[2]}&P62_TIMER=#{p6_time[2]}&P62_TIMER_CNTL=#{p6_timer[2]}" +
|
215
|
+
"&PinNo=P6_3&P63=#{p6[3]}&P63_TIMER=#{p6_time[3]}&P63_TIMER_CNTL=#{p6_timer[3]}" +
|
216
|
+
"&PinNo=P6_4&P64=#{p6[4]}&P64_TIMER=#{p6_time[4]}&P64_TIMER_CNTL=#{p6_timer[4]}" +
|
217
|
+
"&PinNo=P6_5&P65=#{p6[5]}&P65_TIMER=#{p6_time[5]}&P65_TIMER_CNTL=#{p6_timer[5]}" +
|
218
|
+
"&PinNo=P6_6&P66=#{p6[6]}&P66_TIMER=#{p6_time[6]}&P66_TIMER_CNTL=#{p6_timer[6]}" +
|
219
|
+
"&PinNo=P6_7&P67=#{p6[7]}&P67_TIMER=#{p6_time[7]}&P67_TIMER_CNTL=#{p6_timer[7]}" +
|
220
|
+
"&Apply=Apply"
|
221
|
+
|
222
|
+
#a = post.body.split(/&PinNo/)
|
223
|
+
#a.each {|x| print "#{x}\n&PinNo" }
|
224
|
+
|
225
|
+
headers = {
|
226
|
+
'User-Agent' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9) Gecko/2008051206 Firefox/3.0',
|
227
|
+
'Content-Type' => 'application/x-www-form-urlencoded',
|
228
|
+
'Referer' => "http://#{@host}/ioControl_2e.htm",
|
229
|
+
'Cookie' => @cookie
|
230
|
+
}
|
231
|
+
|
232
|
+
response = http.post('/tgi/ioControl.tgi', post.body, headers)
|
233
|
+
#puts response.code
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
#'on2' is short hand for change_state(outlet, PowerController::ON)
|
238
|
+
#Uses the web interface, so unlike 'on', this persists after a device reboot
|
239
|
+
def on2(outlet) #Uses the web interfaces, not SetIO
|
240
|
+
change_state(outlet, @power_on == 1 ? "On" : "Off")
|
241
|
+
end
|
242
|
+
|
243
|
+
#'off2' is short hand for change_state(outlet, PowerController::ON)
|
244
|
+
#Uses the web interface, so unlike 'off', this persists after a device reboot
|
245
|
+
def off2(outlet) #Uses the web interfaces, not SetIO
|
246
|
+
change_state(outlet, @power_off == 0 ? "Off" : "On")
|
247
|
+
end
|
248
|
+
|
249
|
+
#Return a status string, with named ports specified in the port_names array.
|
250
|
+
def to_s(port_names = [nil,nil,nil,nil ])
|
251
|
+
@status.inject_with_index("") { |s,x,i| s + "Port #{i+1}=#{x==0 ? 'On' : 'Off'} #{if port_names[i] then port_names[i] end}\n" }
|
252
|
+
end
|
253
|
+
|
254
|
+
private
|
255
|
+
#change_state uses the web interface to turn relays On or Off
|
256
|
+
#This persists after a device reboot, where the earlier calls do not.
|
257
|
+
#
|
258
|
+
#More Useful is tmp_change_state, as this doesn't get saved on the device.
|
259
|
+
#
|
260
|
+
def change_state(outlet,state)
|
261
|
+
login
|
262
|
+
|
263
|
+
p6 = set_p6
|
264
|
+
p6_time = ["0", "0", "0", "0","0","0","0","0"]
|
265
|
+
p6_timer = ["On","On","On","On","On","On","On","On"]
|
266
|
+
if outlet.class == Array
|
267
|
+
outlet.each { |o| p6[@portmap[o]] = state }
|
268
|
+
else
|
269
|
+
p6[@portmap[outlet]] = state
|
270
|
+
end
|
271
|
+
|
272
|
+
res = Net::HTTP.new(@host, 80).start do |http|
|
273
|
+
|
274
|
+
post = Net::HTTP::Post.new('/tgi/ioControl.tgi')
|
275
|
+
post.body = "PinNo=P6_0&P60=#{p6[0]}&P60_TIMER=#{p6_time[0]}&P60_TIMER_CNTL=#{p6_timer[0]}" +
|
276
|
+
"&PinNo=P6_1&P61=#{p6[1]}&P61_TIMER=#{p6_time[1]}&P61_TIMER_CNTL=#{p6_timer[1]}" +
|
277
|
+
"&PinNo=P6_2&P62=#{p6[2]}&P62_TIMER=#{p6_time[2]}&P62_TIMER_CNTL=#{p6_timer[2]}" +
|
278
|
+
"&PinNo=P6_3&P63=#{p6[3]}&P63_TIMER=#{p6_time[3]}&P63_TIMER_CNTL=#{p6_timer[3]}" +
|
279
|
+
"&PinNo=P6_4&P64=#{p6[4]}&P64_TIMER=#{p6_time[4]}&P64_TIMER_CNTL=#{p6_timer[4]}" +
|
280
|
+
"&PinNo=P6_5&P65=#{p6[5]}&P65_TIMER=#{p6_time[5]}&P65_TIMER_CNTL=#{p6_timer[5]}" +
|
281
|
+
"&PinNo=P6_6&P66=#{p6[6]}&P66_TIMER=#{p6_time[6]}&P66_TIMER_CNTL=#{p6_timer[6]}" +
|
282
|
+
"&PinNo=P6_7&P67=#{p6[7]}&P67_TIMER=#{p6_time[7]}&P67_TIMER_CNTL=#{p6_timer[7]}" +
|
283
|
+
"&Apply=Apply"
|
284
|
+
|
285
|
+
#a = post.body.split(/&PinNo/)
|
286
|
+
#a.each {|x| print "#{x}\n&PinNo" }
|
287
|
+
|
288
|
+
headers = {
|
289
|
+
'User-Agent' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9) Gecko/2008051206 Firefox/3.0',
|
290
|
+
'Content-Type' => 'application/x-www-form-urlencoded',
|
291
|
+
'Referer' => "http://#{@host}/ioControl_2e.htm",
|
292
|
+
'Cookie' => @cookie
|
293
|
+
}
|
294
|
+
|
295
|
+
response = http.post('/tgi/ioControl.tgi', post.body, headers)
|
296
|
+
|
297
|
+
#puts response.code
|
298
|
+
if(response.code.to_i == 200)
|
299
|
+
if outlet.class == Array
|
300
|
+
outlet.each { |o| @status[o-1] = (state == "On" ? 0 : 1) }
|
301
|
+
else
|
302
|
+
@status[outlet-1] = (state == "On" ? 0 : 1)
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
#chonge_state1 takes arguments
|
309
|
+
# outlet, being the relay to change the state of power to the relay
|
310
|
+
#Uses SetIO. Note: changes are lost after power cycle of the 9202.
|
311
|
+
def tmp_change_state(outlet, state)
|
312
|
+
if outlet.class == Array
|
313
|
+
get_str = "/SetIO?"
|
314
|
+
outlet.each_with_index do |o,i|
|
315
|
+
get_str += "+" if i > 0
|
316
|
+
get_str += "P6#{o}=#{state}"
|
317
|
+
end
|
318
|
+
else
|
319
|
+
get_str = "/SetIO?P6#{outlet}=#{state}"
|
320
|
+
end
|
321
|
+
|
322
|
+
Net::HTTP.start(@host) do |http|
|
323
|
+
request = Net::HTTP::Get.new(get_str)
|
324
|
+
request.basic_auth @user, @password
|
325
|
+
response = http.request(request)
|
326
|
+
if response.code.to_i == 200
|
327
|
+
#print response.body
|
328
|
+
if outlet.class == Array
|
329
|
+
outlet.each { |o| @status[o-1] = state }
|
330
|
+
else
|
331
|
+
@status[outlet-1] = state
|
332
|
+
end
|
333
|
+
|
334
|
+
else
|
335
|
+
#print "Connection failed with error #{response.code}\n"
|
336
|
+
raise "Connection failed with error #{response.code}\n"
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
#Authenticates to the IP Powercontroller's web server
|
342
|
+
#Credentials were passed in to PowerController.new()
|
343
|
+
def login #web interface needs a special login
|
344
|
+
res = Net::HTTP.new(@host, 80).start do |http|
|
345
|
+
response = http.get("/")
|
346
|
+
if response.code.to_i == 200
|
347
|
+
challenge = response.body.scan(/NAME=\"Challenge\" VALUE=\n\"(.*)\">/)
|
348
|
+
else
|
349
|
+
#print "Connection failed with error #{response.code}\n"
|
350
|
+
raise "Connection failed with error #{response.code}\n"
|
351
|
+
return
|
352
|
+
end
|
353
|
+
|
354
|
+
#authorize
|
355
|
+
post = Net::HTTP::Post.new('/tgi/login.tgi')
|
356
|
+
post.set_form_data( {"Submitbtn" => "OK", "Username" => "admin", "Password" => "",
|
357
|
+
"Challenge" => "", "Response" => Digest::MD5.hexdigest("admin" + @password + challenge.to_s)} )
|
358
|
+
|
359
|
+
response = http.request(post)
|
360
|
+
if response == nil
|
361
|
+
raise "Failed: no response"
|
362
|
+
elsif response.code.to_i == 200
|
363
|
+
if (response_text = response.response['set-cookie']) != nil
|
364
|
+
@cookie = response_text.split(';')[0]
|
365
|
+
else
|
366
|
+
raise "Failed"
|
367
|
+
end
|
368
|
+
else
|
369
|
+
raise "Failed: #{response.code}"
|
370
|
+
end
|
371
|
+
#puts @cookie
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
# Sets up the p6 array with the devices active ports. Mine has only 4 of 8 available.
|
376
|
+
def set_p6
|
377
|
+
p6 = ["On","On","On","On","On","On","On","On"]
|
378
|
+
@status.each_with_index { |x,i| p6[@portmap[i+1]] = x == 1 ? "Off" : "On" }
|
379
|
+
return p6
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
data/test/test.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require '../lib/powercontroller9202.rb'
|
2
|
+
|
3
|
+
#Default to relay off state being a power on state
|
4
|
+
pc = PowerController9202.new("192.168.249.128", "admin", "xxxxx")
|
5
|
+
|
6
|
+
#change so relay off state is a power off state
|
7
|
+
#pc = PowerController9202.new("192.168.249.128", "admin", "xxxxxx", false)
|
8
|
+
|
9
|
+
#8 relays, not 4
|
10
|
+
#relay off state is a power on state
|
11
|
+
#pc = PowerController9202.new("192.168.249.128", "admin", "xxxxxx", true, 8)
|
12
|
+
|
13
|
+
#Manually set the portmap. Nb portmap[0] is unused.
|
14
|
+
#pc = PowerController9202.new("192.168.249.128", "admin", "xxxxxx")
|
15
|
+
#pc.portmap = [0,0,2,5,7,1,3,4,6]
|
16
|
+
#pc.set_status #to update the status bitmap
|
17
|
+
|
18
|
+
|
19
|
+
puts pc.status.to_s #current relay states as array of 0's and 1's for relay off and on
|
20
|
+
puts pc.to_s(['server', 'modem', 'lights', 'tv']) #outputs relay status with names.
|
21
|
+
puts pc #Prints the relay status (Equivalent to puts pc.to_s )
|
22
|
+
|
23
|
+
######################### EXIT ########################
|
24
|
+
exit #currently testing against an installed controller , as the test version failed.
|
25
|
+
|
26
|
+
#Power on means the relay switch the power on, even if the relay power is off
|
27
|
+
#Relay on, means the relay is powered, but that might mean the power is then off.
|
28
|
+
pc.ensureon #Turns all relays to the power on state (not saved)
|
29
|
+
pc.off([2,4]) #Turns relays 2 and 4 power off (not saved)
|
30
|
+
pc.on([2,4]) #Turns relays 2 and 4 power on (not saved)
|
31
|
+
|
32
|
+
|
33
|
+
pg.toggle_all #Turns power off for 5 seconds through all relays (understands my off is on)
|
34
|
+
pg.toggle_all(10) #Turns power on for 10 seconds through all relays (understands my off is on)
|
35
|
+
|
36
|
+
|
37
|
+
pc.toggle(1) #Turns power off for 5 seconds through relay 1(understands my off is on).
|
38
|
+
pc.toggle(1,10) #Turns power off for 10 seconds through relay 1 (understands my off is on)
|
39
|
+
|
40
|
+
pc.toggle([1,4]) #Turns power off for 5 seconds through relay 1 & 4 (understands my off is on)
|
41
|
+
pc.toggle([2,3],10) #Turns power off for 10 seconds through relays 2 & 3 (understands my off is on).
|
42
|
+
|
43
|
+
#Via the web form, rather thon SetIO
|
44
|
+
pc.reset_all #Sets relays to off state (Relays off, not necessarily power off)
|
45
|
+
#For mine, that is an on state as I want the failure state to be on
|
46
|
+
#The web interface shows them as off though.
|
47
|
+
|
48
|
+
#Via the web form, rather thon SetIO
|
49
|
+
pc.timer_toggle_all #Turns off the relays, then on again after 5 seconds
|
50
|
+
pc.timer_toggle_all(10) #Turns off the relays, then on again after 10 seconds
|
51
|
+
|
52
|
+
#Via the web form, rather thon SetIO
|
53
|
+
pc.on2(3) #Turns relay 3 power on and it shows up that way in the web interface.
|
54
|
+
#Hence will be set this way after the 9202 is power cycled.
|
55
|
+
pc.off2(2) #Turns relay 2 power off and it shows up that way in the web interface.
|
56
|
+
#Hence will be set this way after the 9202 is power cycled.
|
metadata
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: powercontroller9202
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Rob Burrowes
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-10 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rdoc
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.10'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.10'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: hoe
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '3.1'
|
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: '3.1'
|
46
|
+
description: A Ruby GEDCOM to communicate with an Aviosys Inc. 9202 IP Power Controller
|
47
|
+
(and associated products (eg 9212)).
|
48
|
+
email:
|
49
|
+
- r.burrowes@auckland.ac.nz
|
50
|
+
executables: []
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files:
|
53
|
+
- History.txt
|
54
|
+
- Manifest.txt
|
55
|
+
- README.txt
|
56
|
+
files:
|
57
|
+
- History.txt
|
58
|
+
- Manifest.txt
|
59
|
+
- README.txt
|
60
|
+
- Rakefile
|
61
|
+
- lib/powercontroller9202.rb
|
62
|
+
- test/test.rb
|
63
|
+
- .gemtest
|
64
|
+
homepage: https://github.com/rbur004/powercontroller9202
|
65
|
+
licenses: []
|
66
|
+
post_install_message:
|
67
|
+
rdoc_options:
|
68
|
+
- --main
|
69
|
+
- README.txt
|
70
|
+
require_paths:
|
71
|
+
- lib
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
requirements: []
|
85
|
+
rubyforge_project: powercontroller9202
|
86
|
+
rubygems_version: 1.8.24
|
87
|
+
signing_key:
|
88
|
+
specification_version: 3
|
89
|
+
summary: A Ruby GEDCOM to communicate with an Aviosys Inc
|
90
|
+
test_files: []
|