thermostat 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +36 -0
- data/lib/pdp/constants.rb +130 -0
- data/lib/pdp/oid.rb +37 -0
- data/lib/thermostat.rb +95 -0
- metadata +50 -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,50 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.4
|
3
|
+
specification_version: 1
|
4
|
+
name: thermostat
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.0.2
|
7
|
+
date: 2008-03-10 00:00:00 -04:00
|
8
|
+
summary: Ruby modules to control Prolipix IP Thermostats
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: sean at dague dot net
|
12
|
+
homepage: http://rubyforge.net/projects/rtc
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire: thermostat
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Sean Dague
|
31
|
+
files:
|
32
|
+
- lib/thermostat.rb
|
33
|
+
- lib/pdp
|
34
|
+
- lib/pdp/constants.rb
|
35
|
+
- lib/pdp/oid.rb
|
36
|
+
- README
|
37
|
+
test_files: []
|
38
|
+
|
39
|
+
rdoc_options: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- README
|
43
|
+
executables: []
|
44
|
+
|
45
|
+
extensions: []
|
46
|
+
|
47
|
+
requirements: []
|
48
|
+
|
49
|
+
dependencies: []
|
50
|
+
|