saal 0.2.13 → 0.2.14
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +33 -12
- data/TODO +2 -1
- data/bin/saal_readall +0 -0
- data/lib/dinrelay.rb +12 -4
- data/lib/saal.rb +1 -1
- data/saal.gemspec +2 -2
- data/test/dinrelay_test.rb +26 -0
- metadata +4 -4
data/README.rdoc
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
= saal
|
2
2
|
|
3
|
-
saal stands for Sensor and Actuator Abstraction Layer, and it aims to handle the mechanics of accessing sensors and actuators and logging their state over time. In its present state it is capable of reading from any set of one wire sensors attached one or more owserver processes from the owfs project. In the future other forms of sensors as well as actuators can be added.
|
3
|
+
saal stands for Sensor and Actuator Abstraction Layer, and it aims to handle the mechanics of accessing sensors and actuators and logging their state over time. In its present state it is capable of reading from any set of one wire sensors attached one or more owserver processes from the owfs project. It is also able to read and actuate the DIN mounted IP relay from digital loggers (http://www.digital-loggers.com/din.html). In the future other forms of sensors as well as actuators can be added.
|
4
4
|
|
5
|
-
Based on a single definition of available sensors several features are available:
|
5
|
+
Based on a single definition of available sensors/actuators several features are available:
|
6
6
|
|
7
|
-
* An API to read
|
7
|
+
* An API to read/write to sensors/actuators
|
8
8
|
* A daemon that periodically records all sensor values into a MySQL database
|
9
9
|
* An API to interrogate the database of recorded values
|
10
|
-
* A graphing API and
|
10
|
+
* A graphing API and full program to produce charts from the stored sensor reads
|
11
11
|
|
12
12
|
An example of the usage of saal can be seen at http://www.corujas.net.
|
13
13
|
|
@@ -60,16 +60,37 @@ Both arguments to average are unix timestamps in UTC timezone.
|
|
60
60
|
|
61
61
|
== Charting
|
62
62
|
|
63
|
-
|
63
|
+
After you've gotten sensor logging working and some values in the database you can start creating charts based on it. Here's an example /etc/saal/charts.yml file:
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
chart.get_data(now - 60*10, now, 4)
|
70
|
-
#=> [19.1555206999183, 28.3404493331909, 56.4694658915202, 50.4347496032715]
|
65
|
+
day:
|
66
|
+
sensors: [temp_exterior, hum_exterior, pressure]
|
67
|
+
last: 24
|
68
|
+
periods: hours
|
71
69
|
|
72
|
-
|
70
|
+
week:
|
71
|
+
sensors: [temp_exterior, hum_exterior, pressure]
|
72
|
+
last: 7
|
73
|
+
periods: days
|
74
|
+
|
75
|
+
4week:
|
76
|
+
sensors: [temp_exterior, hum_exterior, pressure]
|
77
|
+
last: 4
|
78
|
+
periods: weeks
|
79
|
+
alignlabels: left
|
80
|
+
|
81
|
+
year:
|
82
|
+
sensors: [temp_exterior, hum_exterior, pressure]
|
83
|
+
last: 12
|
84
|
+
periods: months
|
85
|
+
|
86
|
+
4year:
|
87
|
+
sensors: [temp_exterior, hum_exterior, pressure]
|
88
|
+
last: 4
|
89
|
+
periods: years
|
90
|
+
|
91
|
+
With this in place you can now run "saal_chart <some_directory>" and get 5 png files produced with the Google charts API that show the data recorded in the database over the given periods. This is almost exactly the config that generates the graphs at http://www.corujas.net.
|
92
|
+
|
93
|
+
The charting code handles range selection and period naming automatically, so all possibilities of number and type of periods are possible.
|
73
94
|
|
74
95
|
== Author
|
75
96
|
|
data/TODO
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
TODO
|
2
|
-
-
|
2
|
+
- Only enable the outlier proofing for the daemon so things like saal_readall don't block for a long time on unavailable sensors trying to seed the outlier cache
|
3
|
+
- Make the sensor value storage in saal_daemon threaded so a single sensor read can't stall everything else for a long time
|
3
4
|
!-Index the value column of the sensor reads for minimum and maximum
|
4
5
|
- Change the filtering operations (e.g., outliercache) so that the raw value is always stored in the database
|
5
6
|
- Make the outliercache filter based on the expected sensor range (e.g. -20-50 in temperature and 800-1200 in pressure) so as to not be overly sensitive when around 0)
|
data/bin/saal_readall
CHANGED
File without changes
|
data/lib/dinrelay.rb
CHANGED
@@ -29,23 +29,31 @@ module SAAL
|
|
29
29
|
|
30
30
|
class OutletGroup
|
31
31
|
DEFAULT_TIMEOUT = 2
|
32
|
+
DEFAULT_CACHE_TIMEOUT = 60
|
32
33
|
|
33
|
-
|
34
|
+
attr_accessor :host, :port, :user, :pass, :timeout, :cache_timeout
|
34
35
|
|
35
36
|
def initialize(opts={})
|
36
37
|
@host = opts[:host] || opts['host'] || 'localhost'
|
37
38
|
@port = opts[:port] || opts['port'] || 80
|
38
39
|
@user = opts[:user] || opts['user'] || 'admin'
|
39
40
|
@pass = opts[:pass] || opts['pass'] || '1234'
|
40
|
-
@timeout = opts[:timeout] || DEFAULT_TIMEOUT
|
41
|
+
@timeout = opts[:timeout] || opts['timeout'] || DEFAULT_TIMEOUT
|
42
|
+
@cache_timeout = opts[:cache_timeout] || opts['cache_timeout'] || DEFAULT_CACHE_TIMEOUT
|
43
|
+
@cache = nil
|
44
|
+
@cachehit = nil
|
41
45
|
end
|
42
46
|
|
43
47
|
def state(num)
|
44
|
-
|
45
|
-
|
48
|
+
if !@cachetime or @cachetime < Time.now - @cache_timeout
|
49
|
+
@cache = do_get('/index.htm')
|
50
|
+
@cachetime = Time.now
|
51
|
+
end
|
52
|
+
return @cache ? parse_index_html(@cache.body)[num] : nil
|
46
53
|
end
|
47
54
|
|
48
55
|
def set_state(num, state)
|
56
|
+
@cachetime = nil
|
49
57
|
response = do_get("/outlet?#{num}=#{state}")
|
50
58
|
response != nil
|
51
59
|
end
|
data/lib/saal.rb
CHANGED
data/saal.gemspec
CHANGED
@@ -6,8 +6,8 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.platform = Gem::Platform::RUBY
|
7
7
|
|
8
8
|
s.name = 'saal'
|
9
|
-
s.version = '0.2.
|
10
|
-
s.date = '2011-06-
|
9
|
+
s.version = '0.2.14'
|
10
|
+
s.date = '2011-06-21'
|
11
11
|
|
12
12
|
s.summary = "Thin abstraction layer for interfacing and recording sensors (currently onewire) and actuators (currently dinrelay)"
|
13
13
|
s.description = <<EOF
|
data/test/dinrelay_test.rb
CHANGED
@@ -21,6 +21,7 @@ class TestDINRelay < Test::Unit::TestCase
|
|
21
21
|
def do_GET(req, res)
|
22
22
|
sleep @sleep
|
23
23
|
@feedback[:uri] = req.request_uri.to_s
|
24
|
+
@feedback[:nrequests] = (@feedback[:nrequests]||0)+1
|
24
25
|
WEBrick::HTTPAuth.basic_auth(req, res, "My Realm") {|user, pass|
|
25
26
|
user == @user && pass == @pass
|
26
27
|
}
|
@@ -105,6 +106,7 @@ class TestDINRelay < Test::Unit::TestCase
|
|
105
106
|
assert_equal value, sensors.send('name'+num.to_s).read
|
106
107
|
assert_path '/index.htm', feedback[:uri]
|
107
108
|
end
|
109
|
+
assert_equal 1, feedback[:nrequests], "dinrelay request caching not working"
|
108
110
|
end
|
109
111
|
end
|
110
112
|
|
@@ -121,6 +123,30 @@ class TestDINRelay < Test::Unit::TestCase
|
|
121
123
|
end
|
122
124
|
end
|
123
125
|
|
126
|
+
# Test that write invalidates any caching
|
127
|
+
def test_write_read_sensors
|
128
|
+
sensors = SAAL::Sensors.new(TEST_SENSORS_DINRELAY_FILE, TEST_DBCONF)
|
129
|
+
with_webrick(:html=>create_index_html(@vals)) do |feedback|
|
130
|
+
@vals.each do |num, state|
|
131
|
+
sensors.send('name'+num.to_s).write(0.0)
|
132
|
+
sensors.send('name'+num.to_s).read
|
133
|
+
end
|
134
|
+
assert_equal 16, feedback[:nrequests], "dinrelay caching too much"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# Test that the cache times out
|
139
|
+
def test_cache_invalidation
|
140
|
+
sensors = SAAL::Sensors.new(TEST_SENSORS_DINRELAY_FILE, TEST_DBCONF)
|
141
|
+
@og.cache_timeout = 0.1
|
142
|
+
with_webrick(:html=>create_index_html(@vals)) do |feedback|
|
143
|
+
@og.state(1)
|
144
|
+
sleep 0.2
|
145
|
+
@og.state(1)
|
146
|
+
assert_equal 2, feedback[:nrequests], "dinrelay caching not invalidating"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
124
150
|
def test_failed_connection
|
125
151
|
@vals.each do |num, state|
|
126
152
|
assert_equal nil, @og.state(num)
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: saal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 11
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 14
|
10
|
+
version: 0.2.14
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- "Pedro C\xC3\xB4rte-Real"
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-06-
|
18
|
+
date: 2011-06-21 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|