saal 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +460 -0
- data/README.rdoc +76 -0
- data/Rakefile +160 -0
- data/TODO +24 -0
- data/bin/.gitignore +2 -0
- data/bin/dinrelayset +35 -0
- data/bin/dinrelaystatus +32 -0
- data/bin/saal_chart +110 -0
- data/bin/saal_daemon +22 -0
- data/bin/saal_dump_database +11 -0
- data/bin/saal_import_mysql +18 -0
- data/bin/saal_readall +10 -0
- data/lib/chart_data.rb +30 -0
- data/lib/daemon.rb +63 -0
- data/lib/dbstore.rb +86 -0
- data/lib/dinrelay.rb +67 -0
- data/lib/outliercache.rb +53 -0
- data/lib/owsensor.rb +21 -0
- data/lib/saal.rb +23 -0
- data/lib/sensor.rb +100 -0
- data/lib/sensors.rb +48 -0
- data/saal.gemspec +77 -0
- data/test/chart_data_test.rb +39 -0
- data/test/daemon_test.rb +44 -0
- data/test/dbstore_test.rb +70 -0
- data/test/dinrelay.html.erb +143 -0
- data/test/dinrelay_test.rb +112 -0
- data/test/nonexistant_sensor.yml +5 -0
- data/test/outliercache_test.rb +42 -0
- data/test/sensor_test.rb +109 -0
- data/test/sensors_test.rb +77 -0
- data/test/test_db.yml +4 -0
- data/test/test_dinrelay_sensors.yml +16 -0
- data/test/test_helper.rb +37 -0
- data/test/test_sensor_cleanups.yml +21 -0
- data/test/test_sensors.yml +10 -0
- metadata +166 -0
@@ -0,0 +1,112 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/test_helper.rb'
|
2
|
+
require 'webrick'
|
3
|
+
#require 'webrick/accesslog'
|
4
|
+
|
5
|
+
class TestDINRelay < Test::Unit::TestCase
|
6
|
+
SERVICE_OPTS = {:host => 'localhost', :port => 33333,
|
7
|
+
:user => "someuser", :pass =>"somepass"}
|
8
|
+
|
9
|
+
class BasicServing < WEBrick::HTTPServlet::AbstractServlet
|
10
|
+
def self.get_instance(config, opts)
|
11
|
+
new(opts)
|
12
|
+
end
|
13
|
+
def initialize(opts)
|
14
|
+
@html = opts[:html]
|
15
|
+
@user = opts[:user]
|
16
|
+
@pass = opts[:pass]
|
17
|
+
@feedback = opts[:feedback] || {}
|
18
|
+
end
|
19
|
+
def do_GET(req, res)
|
20
|
+
@feedback[:uri] = req.request_uri.to_s
|
21
|
+
WEBrick::HTTPAuth.basic_auth(req, res, "My Realm") {|user, pass|
|
22
|
+
user == @user && pass == @pass
|
23
|
+
}
|
24
|
+
res.body = @html
|
25
|
+
res['Content-Type'] = "text/xml"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def with_webrick(opts)
|
30
|
+
opts = SERVICE_OPTS.merge(opts)
|
31
|
+
|
32
|
+
Socket.do_not_reverse_lookup = true # Speed up startup
|
33
|
+
log = WEBrick::Log.new($stderr, WEBrick::Log::ERROR)
|
34
|
+
access_log = [[log, WEBrick::AccessLog::COMBINED_LOG_FORMAT]]
|
35
|
+
s = WEBrick::HTTPServer.new(:Port => opts[:port],
|
36
|
+
:Logger => log,
|
37
|
+
:AccessLog => access_log)
|
38
|
+
s.mount('/', BasicServing, opts.merge(:feedback => (f = {})))
|
39
|
+
|
40
|
+
thread = Thread.new do
|
41
|
+
s.start
|
42
|
+
end
|
43
|
+
while s.status != :Running; sleep 0.1; end # Make sure the server is up
|
44
|
+
yield f
|
45
|
+
s.shutdown
|
46
|
+
thread.exit
|
47
|
+
end
|
48
|
+
|
49
|
+
def create_index_html(hash)
|
50
|
+
outlets = hash
|
51
|
+
erb = ERB.new(File.open(File.dirname(__FILE__)+'/dinrelay.html.erb').read)
|
52
|
+
erb.result(binding)
|
53
|
+
end
|
54
|
+
|
55
|
+
def setup
|
56
|
+
@og=SAAL::DINRelay::OutletGroup.new(SERVICE_OPTS)
|
57
|
+
@vals={1=>"OFF",2=>"OFF",3=>"ON",4=>"OFF",5=>"ON",6=>"ON",7=>"ON",8=>"OFF"}
|
58
|
+
@rvals={1=>"ON",2=>"ON",3=>"OFF",4=>"ON",5=>"OFF",6=>"OFF",7=>"OFF",8=>"ON"}
|
59
|
+
end
|
60
|
+
|
61
|
+
def assert_path(path, uri)
|
62
|
+
assert_equal "http://localhost:#{SERVICE_OPTS[:port]}"+path, uri
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_read_state
|
66
|
+
with_webrick(:html=>create_index_html(@vals)) do |feedback|
|
67
|
+
@vals.each do |num, state|
|
68
|
+
assert_equal state, @og.state(num)
|
69
|
+
assert_path '/index.htm', feedback[:uri]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_set_state
|
75
|
+
with_webrick(:html=>create_index_html(@rvals)) do |feedback|
|
76
|
+
@vals.each do |num, state|
|
77
|
+
newstate = state == "ON" ? "OFF" : "ON"
|
78
|
+
assert @og.set_state(num,newstate), "State change not working"
|
79
|
+
assert_path "/outlet?#{num}=#{newstate}", feedback[:uri]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_enumerate_sensors
|
85
|
+
sensors = SAAL::Sensors.new(TEST_SENSORS_DINRELAY_FILE, TEST_DBCONF)
|
86
|
+
assert_equal((1..8).map{|i| "name#{i}"}, sensors.map{|s| s.name}.sort)
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_read_sensors
|
90
|
+
sensors = SAAL::Sensors.new(TEST_SENSORS_DINRELAY_FILE, TEST_DBCONF)
|
91
|
+
with_webrick(:html=>create_index_html(@vals)) do |feedback|
|
92
|
+
@vals.each do |num, state|
|
93
|
+
value = state == "ON" ? 1.0 : 0.0
|
94
|
+
assert_equal value, sensors.send('name'+num.to_s).read
|
95
|
+
assert_path '/index.htm', feedback[:uri]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_set_sensors
|
101
|
+
sensors = SAAL::Sensors.new(TEST_SENSORS_DINRELAY_FILE, TEST_DBCONF)
|
102
|
+
with_webrick(:html=>create_index_html(@rvals)) do |feedback|
|
103
|
+
@vals.each do |num, state|
|
104
|
+
newval = state == "ON" ? 0.0 : 1.0
|
105
|
+
newstate = state == "ON" ? "OFF" : "ON"
|
106
|
+
assert_equal newval, sensors.send('name'+num.to_s).write(newval),
|
107
|
+
"State change not working"
|
108
|
+
assert_path "/outlet?#{num}=#{newstate}", feedback[:uri]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/test_helper.rb'
|
2
|
+
|
3
|
+
class TestOutlierCache < Test::Unit::TestCase
|
4
|
+
def test_clean_setup
|
5
|
+
cache = SAAL::OutlierCache.new
|
6
|
+
assert !cache.live, "Live empty cache"
|
7
|
+
20.times {cache.validate(10)}
|
8
|
+
assert cache.live, "Not Live full cache"
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_failed_dirty_setup
|
12
|
+
cache = SAAL::OutlierCache.new
|
13
|
+
assert !cache.live, "Live empty cache"
|
14
|
+
(1..20).each {|i| cache.validate(i)}
|
15
|
+
assert !cache.live, "Live cache with dirty results"
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_working_dirty_setup
|
19
|
+
cache = SAAL::OutlierCache.new
|
20
|
+
assert !cache.live, "Live empty cache"
|
21
|
+
[1,1,1,2,1,1,1,1,1,1,1,1,1].each {|i| cache.validate(i)}
|
22
|
+
assert cache.live, "Not Live full cache"
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_validate
|
26
|
+
cache = SAAL::OutlierCache.new
|
27
|
+
20.times {cache.validate(10)}
|
28
|
+
assert cache.live, "Not Live full cache"
|
29
|
+
assert cache.validate(10), "Non validated good value"
|
30
|
+
assert !cache.validate(15), "Validated bad value"
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_setup_recover_from_discontinuity
|
34
|
+
cache = SAAL::OutlierCache.new
|
35
|
+
20.times {cache.validate(10)}
|
36
|
+
assert cache.live, "Not Live full cache"
|
37
|
+
20.times {cache.validate(15)}
|
38
|
+
assert cache.live, "Not Live full cache"
|
39
|
+
assert cache.validate(15), "Non validated good value"
|
40
|
+
assert !cache.validate(10), "Validated bad value"
|
41
|
+
end
|
42
|
+
end
|
data/test/sensor_test.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/test_helper.rb'
|
2
|
+
|
3
|
+
class MockConnection
|
4
|
+
attr_accessor :value, :values
|
5
|
+
def initialize
|
6
|
+
@value = @values = nil
|
7
|
+
end
|
8
|
+
def read(serial)
|
9
|
+
@value ? @value : @values.shift
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class MockDBStore
|
14
|
+
attr_accessor :value
|
15
|
+
def average(sensor, from, to)
|
16
|
+
@value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class TestSensor < Test::Unit::TestCase
|
21
|
+
def fake_sensor(name, opts={})
|
22
|
+
SAAL::Sensors.sensors_from_defs(@dbstore, name, @defs[name],
|
23
|
+
opts.merge(:owconn => @conn))[0]
|
24
|
+
end
|
25
|
+
|
26
|
+
def setup
|
27
|
+
@defs = YAML::load File.new(TEST_SENSOR_CLEANUPS_FILE)
|
28
|
+
@conn = MockConnection.new
|
29
|
+
@dbstore = MockDBStore.new
|
30
|
+
@fake = fake_sensor('fake', :no_outliercache => true)
|
31
|
+
@fake2 = fake_sensor('fake2', :no_outliercache => true)
|
32
|
+
@fake3 = fake_sensor('fake3')
|
33
|
+
@max_value = @defs['fake2']['max_value']
|
34
|
+
@max_correctable = @defs['fake2']['max_correctable']
|
35
|
+
@min_value = @defs['fake2']['min_value']
|
36
|
+
@min_correctable = @defs['fake2']['min_correctable']
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_read_too_high_values
|
40
|
+
@conn.value = @max_value+1
|
41
|
+
assert_nil @fake.read
|
42
|
+
assert_nil @fake.read_uncached
|
43
|
+
@conn.value = @max_value
|
44
|
+
assert_equal @max_value, @fake.read
|
45
|
+
assert_equal @max_value, @fake.read_uncached
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_read_too_high_but_correctable_values
|
49
|
+
@conn.value = @max_correctable
|
50
|
+
assert_equal @max_value, @fake2.read
|
51
|
+
assert_equal @max_value, @fake2.read_uncached
|
52
|
+
@conn.value = @max_correctable+1
|
53
|
+
assert_nil @fake2.read
|
54
|
+
assert_nil @fake2.read_uncached
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_read_too_low_values
|
58
|
+
@conn.value = @min_value-1
|
59
|
+
assert_nil @fake.read
|
60
|
+
assert_nil @fake.read_uncached
|
61
|
+
@conn.value = @min_value
|
62
|
+
assert_equal @min_value, @fake.read
|
63
|
+
assert_equal @min_value, @fake.read_uncached
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_read_too_low_but_correctable_values
|
67
|
+
@conn.value = @min_correctable
|
68
|
+
assert_equal @min_value, @fake2.read
|
69
|
+
assert_equal @min_value, @fake2.read_uncached
|
70
|
+
@conn.value = @min_correctable-1
|
71
|
+
assert_nil @fake2.read
|
72
|
+
assert_nil @fake2.read_uncached
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_read_without_limits
|
76
|
+
@conn.value = 200
|
77
|
+
assert_equal 200, @fake3.read
|
78
|
+
assert_equal 200, @fake3.read_uncached
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_eliminate_outliers
|
82
|
+
@conn.values = [200]*20 + [1000,200]
|
83
|
+
assert_equal [200]*21, (1..21).map{@fake3.read}
|
84
|
+
@conn.values = [200]*20 + [1000,200,1000,200]
|
85
|
+
assert_equal [200]*21, (1..21).map{@fake3.read_uncached}
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_eliminate_outliers_zeroes
|
89
|
+
@conn.values = [0]*20 + [1000,0]
|
90
|
+
assert_equal [0]*20+[1000], (1..21).map{@fake3.read}
|
91
|
+
@conn.values = [0]*20 + [1000,0]
|
92
|
+
assert_equal [0]*20+[1000], (1..21).map{@fake3.read_uncached}
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_mocked
|
96
|
+
@mockable = fake_sensor('fake3')
|
97
|
+
@conn.value = 1.0
|
98
|
+
assert_equal 1.0, @mockable.read
|
99
|
+
@mockable.mock_set(:value => 2.0)
|
100
|
+
assert_equal 2.0, @mockable.read
|
101
|
+
@mockable.write(3.0)
|
102
|
+
assert_equal 3.0, @mockable.read
|
103
|
+
@mockable.mock_set(:minimum => 1.0, :average => 2.0, :maximum => 3.0)
|
104
|
+
assert_equal 1.0, @mockable.minimum(0,100)
|
105
|
+
assert_equal 2.0, @mockable.average(0,100)
|
106
|
+
assert_equal 3.0, @mockable.maximum(0,100)
|
107
|
+
assert_equal 3.0, @mockable.read
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/test_helper.rb'
|
2
|
+
|
3
|
+
class TestSensors < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@defs = YAML::load File.new(TEST_SENSORS_FILE)
|
6
|
+
@sensors = SAAL::Sensors.new(TEST_SENSORS_FILE, TEST_DBCONF)
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_get_sensor
|
10
|
+
@defs.each do |name, value|
|
11
|
+
s = @sensors.send name
|
12
|
+
assert_equal s.description, value['name']
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_read
|
17
|
+
with_fake_owserver do
|
18
|
+
assert_instance_of Float, @sensors.fake_temp.read
|
19
|
+
assert_nil @sensors.non_existant.read
|
20
|
+
assert_raise(NoMethodError) { @sensors.no_such_name.read }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_read_uncached
|
25
|
+
with_fake_owserver do
|
26
|
+
assert_instance_of Float, @sensors.fake_temp.read_uncached
|
27
|
+
assert_nil @sensors.non_existant.read_uncached
|
28
|
+
assert_raise(NoMethodError) { @sensors.no_such_name.read_uncached }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_each
|
33
|
+
expected = @defs.map{ |name, value| value['name']}
|
34
|
+
assert_equal expected, @sensors.map {|sensor| sensor.description}
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_writeable
|
38
|
+
dinsensors = SAAL::Sensors.new(TEST_SENSORS_DINRELAY_FILE, TEST_DBCONF)
|
39
|
+
dinsensors.each {|s| assert s.writeable?}
|
40
|
+
owsensors = SAAL::Sensors.new(TEST_SENSORS_FILE, TEST_DBCONF)
|
41
|
+
owsensors.each {|s| assert !s.writeable?}
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_average
|
45
|
+
db_setup
|
46
|
+
|
47
|
+
test_values = [[10, 7.323],[12, 5.432],[23, -2.125], [44, 0.123]]
|
48
|
+
test_average = (5.432 - 2.125)/2.0
|
49
|
+
test_values.each do |values|
|
50
|
+
@dbstore.write(:fake_temp, *values)
|
51
|
+
end
|
52
|
+
|
53
|
+
assert_instance_of Float, @sensors.fake_temp.average(11, 25)
|
54
|
+
assert_in_delta test_average, @sensors.fake_temp.average(11, 25), 0.001
|
55
|
+
assert_in_delta test_average, @sensors.fake_temp.average(12, 25), 0.001
|
56
|
+
assert_in_delta test_average, @sensors.fake_temp.average(11, 23), 0.001
|
57
|
+
|
58
|
+
# when there are no points it's nil
|
59
|
+
assert_nil @sensors.fake_temp.average(50, 60)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_store_value
|
63
|
+
db_setup
|
64
|
+
|
65
|
+
with_fake_owserver do
|
66
|
+
@sensors.fake_temp.store_value
|
67
|
+
end
|
68
|
+
|
69
|
+
db_test_query("SELECT * FROM sensor_reads") do |res|
|
70
|
+
assert_equal 1, res.num_rows
|
71
|
+
row = res.fetch_row
|
72
|
+
assert_equal "fake_temp", row[0]
|
73
|
+
assert_in_delta Time.now.utc.to_i, row[1], 100
|
74
|
+
assert_instance_of Float, row[2].to_f
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/test/test_db.yml
ADDED
data/test/test_helper.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'yaml'
|
3
|
+
require 'fileutils'
|
4
|
+
require File.dirname(__FILE__)+'/../lib/saal.rb'
|
5
|
+
|
6
|
+
class Test::Unit::TestCase
|
7
|
+
TEST_SENSORS_FILE = File.dirname(__FILE__)+'/test_sensors.yml'
|
8
|
+
TEST_SENSORS_DINRELAY_FILE = File.dirname(__FILE__)+'/test_dinrelay_sensors.yml'
|
9
|
+
TEST_SENSOR_CLEANUPS_FILE = File.dirname(__FILE__)+'/test_sensor_cleanups.yml'
|
10
|
+
TEST_NONEXIST_SENSOR_FILE = File.dirname(__FILE__)+'/nonexistant_sensor.yml'
|
11
|
+
TEST_DBCONF = File.dirname(__FILE__)+'/test_db.yml'
|
12
|
+
TEST_DBOPTS = YAML::load(File.new(TEST_DBCONF))
|
13
|
+
|
14
|
+
def with_fake_owserver
|
15
|
+
pid = fork do
|
16
|
+
exec("owserver", "--fake", "1F,10", "--foreground")
|
17
|
+
end
|
18
|
+
sleep 1 # Potential timing bug when the system is under load
|
19
|
+
yield
|
20
|
+
Process.kill("KILL", pid)
|
21
|
+
Process.waitpid(pid)
|
22
|
+
end
|
23
|
+
|
24
|
+
def db_setup
|
25
|
+
@dbstore = SAAL::DBStore.new(TEST_DBCONF)
|
26
|
+
@dbstore.db_wipe
|
27
|
+
@dbstore.db_initialize
|
28
|
+
end
|
29
|
+
|
30
|
+
def db_test_query(query)
|
31
|
+
db = Mysql.new(TEST_DBOPTS['host'],TEST_DBOPTS['user'],
|
32
|
+
TEST_DBOPTS['pass'],TEST_DBOPTS['db'])
|
33
|
+
res = db.query(query)
|
34
|
+
yield res
|
35
|
+
db.close
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
fake:
|
2
|
+
name: "A fake temperature sensor"
|
3
|
+
max_value: 500
|
4
|
+
min_value: 100
|
5
|
+
onewire:
|
6
|
+
serial: /10.4AEC29CDBAAB/temperature
|
7
|
+
|
8
|
+
fake2:
|
9
|
+
name: "A fake temperature sensor"
|
10
|
+
max_value: 500
|
11
|
+
max_correctable: 550
|
12
|
+
min_value: 100
|
13
|
+
min_correctable: 50
|
14
|
+
onewire:
|
15
|
+
serial: /10.4AEC29CDBAAB/temperature
|
16
|
+
|
17
|
+
fake3:
|
18
|
+
name: "A fake temperature sensor"
|
19
|
+
onewire:
|
20
|
+
serial: /10.4AEC29CDBAAB/temperature
|
21
|
+
|
metadata
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: saal
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 19
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
- 2
|
10
|
+
version: 0.2.2
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- "Pedro C\xC3\xB4rte-Real"
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-12-29 00:00:00 +00:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: ownet
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 27
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 1
|
33
|
+
- 0
|
34
|
+
version: 0.1.0
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: nokogiri
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 3
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
version: "0"
|
49
|
+
type: :runtime
|
50
|
+
version_requirements: *id002
|
51
|
+
- !ruby/object:Gem::Dependency
|
52
|
+
name: mysql
|
53
|
+
prerelease: false
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 3
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
version: "0"
|
63
|
+
type: :runtime
|
64
|
+
version_requirements: *id003
|
65
|
+
description: |
|
66
|
+
A daemon and libraries to create an abstraction layer that interfaces with
|
67
|
+
sensors and actuators, recording their state, responding to requests
|
68
|
+
for current and historical values, and allowing changes of state.
|
69
|
+
|
70
|
+
email: pedro@pedrocr.net
|
71
|
+
executables:
|
72
|
+
- saal_readall
|
73
|
+
- saal_dump_database
|
74
|
+
- dinrelayset
|
75
|
+
- dinrelaystatus
|
76
|
+
- saal_import_mysql
|
77
|
+
- saal_daemon
|
78
|
+
- saal_chart
|
79
|
+
extensions: []
|
80
|
+
|
81
|
+
extra_rdoc_files:
|
82
|
+
- README.rdoc
|
83
|
+
- LICENSE
|
84
|
+
files:
|
85
|
+
- LICENSE
|
86
|
+
- README.rdoc
|
87
|
+
- Rakefile
|
88
|
+
- TODO
|
89
|
+
- bin/.gitignore
|
90
|
+
- bin/dinrelayset
|
91
|
+
- bin/dinrelaystatus
|
92
|
+
- bin/saal_chart
|
93
|
+
- bin/saal_daemon
|
94
|
+
- bin/saal_dump_database
|
95
|
+
- bin/saal_import_mysql
|
96
|
+
- bin/saal_readall
|
97
|
+
- lib/chart_data.rb
|
98
|
+
- lib/daemon.rb
|
99
|
+
- lib/dbstore.rb
|
100
|
+
- lib/dinrelay.rb
|
101
|
+
- lib/outliercache.rb
|
102
|
+
- lib/owsensor.rb
|
103
|
+
- lib/saal.rb
|
104
|
+
- lib/sensor.rb
|
105
|
+
- lib/sensors.rb
|
106
|
+
- saal.gemspec
|
107
|
+
- test/chart_data_test.rb
|
108
|
+
- test/daemon_test.rb
|
109
|
+
- test/dbstore_test.rb
|
110
|
+
- test/dinrelay.html.erb
|
111
|
+
- test/dinrelay_test.rb
|
112
|
+
- test/nonexistant_sensor.yml
|
113
|
+
- test/outliercache_test.rb
|
114
|
+
- test/sensor_test.rb
|
115
|
+
- test/sensors_test.rb
|
116
|
+
- test/test_db.yml
|
117
|
+
- test/test_dinrelay_sensors.yml
|
118
|
+
- test/test_helper.rb
|
119
|
+
- test/test_sensor_cleanups.yml
|
120
|
+
- test/test_sensors.yml
|
121
|
+
has_rdoc: true
|
122
|
+
homepage: https://github.com/pedrocr/saal
|
123
|
+
licenses: []
|
124
|
+
|
125
|
+
post_install_message:
|
126
|
+
rdoc_options:
|
127
|
+
- -S
|
128
|
+
- -w 2
|
129
|
+
- -N
|
130
|
+
- -c utf8
|
131
|
+
require_paths:
|
132
|
+
- lib
|
133
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
134
|
+
none: false
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
hash: 3
|
139
|
+
segments:
|
140
|
+
- 0
|
141
|
+
version: "0"
|
142
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
143
|
+
none: false
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
hash: 3
|
148
|
+
segments:
|
149
|
+
- 0
|
150
|
+
version: "0"
|
151
|
+
requirements: []
|
152
|
+
|
153
|
+
rubyforge_project:
|
154
|
+
rubygems_version: 1.3.7
|
155
|
+
signing_key:
|
156
|
+
specification_version: 2
|
157
|
+
summary: Thin abstraction layer for interfacing and recording sensors (currently onewire) and actuators (currently dinrelay)
|
158
|
+
test_files:
|
159
|
+
- test/chart_data_test.rb
|
160
|
+
- test/daemon_test.rb
|
161
|
+
- test/dbstore_test.rb
|
162
|
+
- test/dinrelay_test.rb
|
163
|
+
- test/outliercache_test.rb
|
164
|
+
- test/sensor_test.rb
|
165
|
+
- test/sensors_test.rb
|
166
|
+
- test/test_helper.rb
|