sdague-thermostat 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/README +36 -0
  2. data/lib/pdp/constants.rb +130 -0
  3. data/lib/pdp/oid.rb +37 -0
  4. data/lib/thermostat.rb +95 -0
  5. metadata +57 -0
data/README ADDED
@@ -0,0 +1,36 @@
1
+ Copyright (c) 2008 - Sean Dague <sean at dague dot net>
2
+
3
+ THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS
4
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
5
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
6
+ DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
7
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
8
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
9
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
10
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
11
+ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
12
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
13
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
+
15
+
16
+ This code is based on the Proliphix Software API which can be found
17
+ here ( http://www.proliphix.com/Documentation.aspx ). I am writing
18
+ this software to interface with my NT20e unit. The API looks to be
19
+ the same across all their IP units, but I will only be testing on my
20
+ unit in my house.
21
+
22
+ Important notices from the manual:
23
+
24
+ **Limitations on the Frequency of Operations**
25
+
26
+ While the device can handle numerous back to back requests, it is
27
+ advisable to not sustain an operation frequency higher than 1 request
28
+ per 60 second period for a substantial amount of time. In other words,
29
+ sustained polling of the device should not exceed a few requests per
30
+ minute. A prolonged burst of requests higher than 1 request per 60
31
+ second period may degrade the main function of the thermostat. Also,
32
+ if one is making a PIB set and wishes to observe a reaction from the
33
+ device, it is advisable to wait for at least 1 second between the set
34
+ request and subsequent get request.
35
+
36
+
@@ -0,0 +1,130 @@
1
+
2
+ module Proliphix
3
+ # a whole crap load of constants for the proliphix API
4
+
5
+ # read/write
6
+ ThermHvacMode = OID.new("HVAC Mode",
7
+ "4.1.1",
8
+ false,
9
+ {
10
+ 1 => "Off",
11
+ 2 => "Heat",
12
+ 3 => "Cool",
13
+ 4 => "Auto",
14
+ })
15
+
16
+ ThermHvacState = OID.new("HVAC State",
17
+ "4.1.2",
18
+ true,
19
+ {
20
+ 1 => "Initializing",
21
+ 2 => "Off",
22
+ 3 => "Heat",
23
+ 4 => "Heat2",
24
+ 5 => "Heat3",
25
+ 6 => "Cool",
26
+ 7 => "Cool2",
27
+ 8 => "Delay",
28
+ 9 => "ResetRelays"
29
+ })
30
+
31
+ ThermFanMode = OID.new("Fan Mode",
32
+ "4.1.3",
33
+ false,
34
+ {
35
+ 1 => "Auto",
36
+ 2 => "On",
37
+ 3 => "Schedule",
38
+ })
39
+
40
+ ThermFanState = OID.new("Fan State",
41
+ "4.1.4",
42
+ true,
43
+ {
44
+ 0 => "Init",
45
+ 1 => "Off",
46
+ 2 => "On",
47
+ })
48
+
49
+ ThermSetbackHeat = OID.new("Setback Heat",
50
+ "4.1.5",
51
+ false)
52
+
53
+ ThermSetbackCool = OID.new("Setback Cool",
54
+ "4.1.6",
55
+ false)
56
+
57
+ # only on the NT150, and the math won't really work on this now anyway
58
+ ThermConfigHumidyCool = OID.new("thermConfigHumidityCool",
59
+ "4.2.22",
60
+ false)
61
+
62
+ ThermSetbackStatus = OID.new("Setback Status",
63
+ "4.1.9",
64
+ false,
65
+ {
66
+ 1 => "Normal",
67
+ 2 => "Hold",
68
+ 3 => "Override"
69
+ })
70
+
71
+ ThermCurrentPeriod = OID.new("Current Period",
72
+ "4.1.10",
73
+ true, # false, but the spec says writes are ignored
74
+ {
75
+ 1 => "Morn",
76
+ 2 => "Day",
77
+ 3 => "Eve",
78
+ 4 => "Night",
79
+ })
80
+
81
+ ThermActivePeriod = OID.new("Activity Period",
82
+ "4.1.12",
83
+ true,
84
+ {
85
+ 1 => "Morn",
86
+ 2 => "Day",
87
+ 3 => "Eve",
88
+ 4 => "Night",
89
+ 5 => "Hold",
90
+ 6 => "Override"
91
+ })
92
+
93
+ ThermCurrentClass = OID.new("Current Day Class",
94
+ "4.1.11",
95
+ true,
96
+ {
97
+ 1 => "In",
98
+ 2 => "Out",
99
+ 3 => "Away"
100
+ })
101
+
102
+ ThermAverageTemp = OID.new("Temperature (degrees F)",
103
+ "4.1.13",
104
+ true)
105
+
106
+ ThermHeat1Usage = OID.new("Heat Usage (minutes)",
107
+ "4.5.1",
108
+ true, nil, false) # it says false, but that's just too hard for me to wrap my brain around
109
+
110
+ ThermHeat2Usage = OID.new("Heat 2 Usage (minutes)",
111
+ "4.5.2",
112
+ true, nil, false) # it says false, but that's just too hard for me to wrap my brain around
113
+
114
+ ThermCool1Usage = OID.new("Cooling Usage (minutes)",
115
+ "4.5.3",
116
+ true, nil, false) # it says false, but that's just too hard for me to wrap my brain around
117
+
118
+ ThermCool2Usage = OID.new("Cooling 2 Usage (minutes)",
119
+ "4.5.4",
120
+ true, nil, false) # it says false, but that's just too hard for me to wrap my brain around
121
+
122
+ ThermFanUsage = OID.new("Fan Usage (minutes)",
123
+ "4.5.5",
124
+ true, nil, false)
125
+
126
+ ThermLastUsageReset = OID.new("Last Usage Reset",
127
+ "4.5.6",
128
+ false, nil, false) # we're going to have to be tricky about this one
129
+
130
+ end
data/lib/pdp/oid.rb ADDED
@@ -0,0 +1,37 @@
1
+ module Proliphix
2
+ class OID
3
+ def initialize(name, oid, readonly, valuemap = nil, scale = true)
4
+ @name = name
5
+ @oid = oid
6
+ @valuemap = valuemap
7
+ @readonly = readonly
8
+ @scale = scale
9
+ end
10
+
11
+ def oid
12
+ return @oid
13
+ end
14
+
15
+ def name
16
+ return @name
17
+ end
18
+
19
+ def ro?
20
+ return @readonly
21
+ end
22
+
23
+ # a little tricky, but not too bad. Basically the access
24
+ # gives us either the value off the value map, or the degrees
25
+ # reading (as we always get degrees as 10x ints)
26
+
27
+ def [](value)
28
+ if @valuemap
29
+ return @valuemap[value.to_i]
30
+ elsif @scale
31
+ return value.to_i / 10.0
32
+ else
33
+ return value.to_i
34
+ end
35
+ end
36
+ end
37
+ end
data/lib/thermostat.rb ADDED
@@ -0,0 +1,95 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'open-uri'
4
+
5
+ # order here is important
6
+ require 'pdp/oid'
7
+ require 'pdp/constants'
8
+
9
+ # Some docs
10
+ class Thermostat
11
+
12
+ def initialize(ip, user, passwd)
13
+ @ip = ip
14
+ @user = user
15
+ @passwd = passwd
16
+ @fetched = {}
17
+ @sensors = []
18
+ end
19
+
20
+ def [](reading)
21
+ return @fetched[reading]
22
+ end
23
+
24
+ def url
25
+ return "http://#{@ip}"
26
+ end
27
+
28
+ def set_senors(*array)
29
+ @sensors = array
30
+ return self
31
+ end
32
+
33
+ def get_query_url
34
+ query = ""
35
+ for item in @sensors
36
+ if query != ""
37
+ query += "&"
38
+ end
39
+ query += "OID#{item.oid}="
40
+ end
41
+ query = url + "/get?" + query
42
+ end
43
+
44
+ def set_query_url(mod, value)
45
+ query = "OID#{mod.oid}=#{value}"
46
+ query = url + "/pdp?" + query + "&sumbit=Submit"
47
+ end
48
+
49
+ # Because of the timing issues with the thermostat we want to get all the data we can in one packet.
50
+ def fetch_data()
51
+ open(get_query_url, :http_basic_authentication => [@user, @passwd]) do |line|
52
+ parse_data(line.read)
53
+ end
54
+ return self
55
+ end
56
+
57
+ def set_data(mod, value)
58
+ unless mod.ro?
59
+ open(set_query_url(mod, value), :http_basic_authentication => [@user, @passwd]) do |line|
60
+ parse_data(line.read)
61
+ end
62
+ end
63
+ return self
64
+ end
65
+
66
+
67
+ def parse_data(raw_data)
68
+ results = raw_data.split('&')
69
+ results.each do |r|
70
+ (oid, value) = r.split('=')
71
+ mod = lookup_oid(oid)
72
+ if mod
73
+ @fetched[mod] = mod[value]
74
+ end
75
+ end
76
+ end
77
+
78
+ def lookup_oid(oid)
79
+ newid = oid.sub(/^OID/, '')
80
+ @sensors.each do |s|
81
+ if s.oid == newid
82
+ return s
83
+ end
84
+ end
85
+ return nil
86
+ end
87
+
88
+ def to_s
89
+ s = ""
90
+ @fetched.each do |k, v|
91
+ s += "#{k.name}: #{v}\n"
92
+ end
93
+ return s
94
+ end
95
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sdague-thermostat
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Sean Dague
8
+ autorequire: thermostat
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-12-22 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: sean at dague dot net
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ files:
25
+ - lib/thermostat.rb
26
+ - lib/pdp
27
+ - lib/pdp/constants.rb
28
+ - lib/pdp/oid.rb
29
+ - README
30
+ has_rdoc: true
31
+ homepage: http://rubyforge.net/projects/rtc
32
+ post_install_message:
33
+ rdoc_options: []
34
+
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: "0"
42
+ version:
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ requirements: []
50
+
51
+ rubyforge_project:
52
+ rubygems_version: 1.2.0
53
+ signing_key:
54
+ specification_version: 2
55
+ summary: Ruby modules to control Prolipix IP Thermostats
56
+ test_files: []
57
+