saal 0.2.25 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/saal_denkovi_relays +34 -0
- data/bin/saal_envoy_generate_config +53 -0
- data/bin/saal_envoy_read +152 -0
- data/lib/chart.rb +1 -1
- data/lib/chart_data.rb +1 -1
- data/lib/dbstore.rb +41 -18
- data/lib/denkovi.rb +101 -0
- data/lib/dinrelay.rb +3 -19
- data/lib/envoy.rb +287 -0
- data/lib/http.rb +51 -0
- data/lib/outliercache.rb +1 -1
- data/lib/saal.rb +5 -2
- data/lib/sensor.rb +5 -0
- data/lib/sensors.rb +31 -2
- data/saal.gemspec +16 -5
- data/test/chart_data_test.rb +1 -1
- data/test/chart_test.rb +0 -3
- data/test/daemon_test.rb +2 -2
- data/test/dbstore_test.rb +20 -2
- data/test/denkovi.json.erb +39 -0
- data/test/denkovi_test.rb +212 -0
- data/test/dinrelay_test.rb +1 -1
- data/test/sensor_test.rb +7 -1
- data/test/sensors_test.rb +5 -5
- data/test/test_db.yml +3 -3
- data/test/test_denkovi_sensors.yml +39 -0
- data/test/test_helper.rb +2 -2
- data/test/test_sensors.yml +1 -1
- metadata +72 -42
- data/bin/saal_chart~ +0 -90
- data/bin/saal_daemon~ +0 -31
data/test/sensors_test.rb
CHANGED
@@ -67,11 +67,11 @@ class TestSensors < Test::Unit::TestCase
|
|
67
67
|
end
|
68
68
|
|
69
69
|
db_test_query("SELECT * FROM sensor_reads") do |res|
|
70
|
-
assert_equal 1, res.
|
71
|
-
row = res.
|
72
|
-
assert_equal "fake_temp", row[
|
73
|
-
assert_in_delta Time.now.utc.to_i, row[
|
74
|
-
assert_instance_of Float, row[
|
70
|
+
assert_equal 1, res.count
|
71
|
+
row = res.first
|
72
|
+
assert_equal "fake_temp", row["sensor"]
|
73
|
+
assert_in_delta Time.now.utc.to_i, row["date"].to_i, 100
|
74
|
+
assert_instance_of Float, row["value"].to_f
|
75
75
|
end
|
76
76
|
end
|
77
77
|
end
|
data/test/test_db.yml
CHANGED
@@ -1,4 +1,4 @@
|
|
1
1
|
host: localhost
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
username: sensor_reads
|
3
|
+
password: password
|
4
|
+
database: sensor_reads_test
|
@@ -0,0 +1,39 @@
|
|
1
|
+
group1:
|
2
|
+
denkovi:
|
3
|
+
host: localhost
|
4
|
+
port: 33333
|
5
|
+
pass: somepass
|
6
|
+
outlets:
|
7
|
+
1: name01
|
8
|
+
2: name02
|
9
|
+
3: name03
|
10
|
+
4: name04
|
11
|
+
5: name05
|
12
|
+
6: name06
|
13
|
+
7: name07
|
14
|
+
8: name08
|
15
|
+
9: name09
|
16
|
+
10: name10
|
17
|
+
11: name11
|
18
|
+
12: name12
|
19
|
+
13: name13
|
20
|
+
14: name14
|
21
|
+
15: name15
|
22
|
+
16: name16
|
23
|
+
descriptions:
|
24
|
+
1: description01
|
25
|
+
2: description02
|
26
|
+
3: description03
|
27
|
+
4: description04
|
28
|
+
5: description05
|
29
|
+
6: description06
|
30
|
+
7: description07
|
31
|
+
8: description08
|
32
|
+
9: description09
|
33
|
+
10: description10
|
34
|
+
11: description11
|
35
|
+
12: description12
|
36
|
+
13: description13
|
37
|
+
14: description14
|
38
|
+
15: description15
|
39
|
+
16: description16
|
data/test/test_helper.rb
CHANGED
@@ -6,6 +6,7 @@ require File.dirname(__FILE__)+'/../lib/saal.rb'
|
|
6
6
|
class Test::Unit::TestCase
|
7
7
|
TEST_SENSORS_FILE = File.dirname(__FILE__)+'/test_sensors.yml'
|
8
8
|
TEST_SENSORS_DINRELAY_FILE = File.dirname(__FILE__)+'/test_dinrelay_sensors.yml'
|
9
|
+
TEST_SENSORS_DENKOVI_FILE = File.dirname(__FILE__)+'/test_denkovi_sensors.yml'
|
9
10
|
TEST_SENSOR_CLEANUPS_FILE = File.dirname(__FILE__)+'/test_sensor_cleanups.yml'
|
10
11
|
TEST_NONEXIST_SENSOR_FILE = File.dirname(__FILE__)+'/nonexistant_sensor.yml'
|
11
12
|
TEST_CHARTS_FILE = File.dirname(__FILE__)+'/test_charts.yml'
|
@@ -29,8 +30,7 @@ class Test::Unit::TestCase
|
|
29
30
|
end
|
30
31
|
|
31
32
|
def db_test_query(query)
|
32
|
-
db =
|
33
|
-
TEST_DBOPTS['pass'],TEST_DBOPTS['db'])
|
33
|
+
db = Mysql2::Client.new(TEST_DBOPTS)
|
34
34
|
res = db.query(query)
|
35
35
|
yield res
|
36
36
|
db.close
|
data/test/test_sensors.yml
CHANGED
metadata
CHANGED
@@ -1,63 +1,86 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: saal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.3.4
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Pedro Côrte-Real
|
9
|
-
autorequire:
|
8
|
+
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2021-04-04 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: ownet
|
16
|
-
requirement:
|
17
|
-
none: false
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version: 0.2
|
19
|
+
version: '0.2'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
|
-
version_requirements:
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: mysql2
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.5'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.5'
|
25
41
|
- !ruby/object:Gem::Dependency
|
26
42
|
name: nokogiri
|
27
|
-
requirement:
|
28
|
-
none: false
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
29
44
|
requirements:
|
30
|
-
- -
|
45
|
+
- - "~>"
|
31
46
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
47
|
+
version: '1.8'
|
33
48
|
type: :runtime
|
34
49
|
prerelease: false
|
35
|
-
version_requirements:
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.8'
|
36
55
|
- !ruby/object:Gem::Dependency
|
37
|
-
name:
|
38
|
-
requirement:
|
39
|
-
none: false
|
56
|
+
name: net-http-digest_auth
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
40
58
|
requirements:
|
41
|
-
- -
|
59
|
+
- - "~>"
|
42
60
|
- !ruby/object:Gem::Version
|
43
|
-
version: '
|
61
|
+
version: '1.4'
|
44
62
|
type: :runtime
|
45
63
|
prerelease: false
|
46
|
-
version_requirements:
|
47
|
-
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.4'
|
69
|
+
description: "A daemon and libraries to create an abstraction layer that interfaces
|
48
70
|
with \nsensors and actuators, recording their state, responding to requests \nfor
|
49
71
|
current and historical values, and allowing changes of state.\n"
|
50
72
|
email: pedro@pedrocr.net
|
51
73
|
executables:
|
52
|
-
- saal_chart~
|
53
74
|
- dinrelaystatus
|
54
|
-
- saal_readall
|
55
|
-
- saal_dump_database
|
56
|
-
- saal_daemon
|
57
|
-
- saal_chart
|
58
|
-
- saal_daemon~
|
59
75
|
- dinrelayset
|
60
76
|
- saal_import_mysql
|
77
|
+
- saal_dump_database
|
78
|
+
- saal_readall
|
79
|
+
- saal_denkovi_relays
|
80
|
+
- saal_chart
|
81
|
+
- saal_daemon
|
82
|
+
- saal_envoy_generate_config
|
83
|
+
- saal_envoy_read
|
61
84
|
extensions: []
|
62
85
|
extra_rdoc_files:
|
63
86
|
- README.rdoc
|
@@ -72,7 +95,10 @@ files:
|
|
72
95
|
- bin/dinrelaystatus
|
73
96
|
- bin/saal_chart
|
74
97
|
- bin/saal_daemon
|
98
|
+
- bin/saal_denkovi_relays
|
75
99
|
- bin/saal_dump_database
|
100
|
+
- bin/saal_envoy_generate_config
|
101
|
+
- bin/saal_envoy_read
|
76
102
|
- bin/saal_import_mysql
|
77
103
|
- bin/saal_readall
|
78
104
|
- lib/chart.rb
|
@@ -80,7 +106,10 @@ files:
|
|
80
106
|
- lib/charts.rb
|
81
107
|
- lib/daemon.rb
|
82
108
|
- lib/dbstore.rb
|
109
|
+
- lib/denkovi.rb
|
83
110
|
- lib/dinrelay.rb
|
111
|
+
- lib/envoy.rb
|
112
|
+
- lib/http.rb
|
84
113
|
- lib/outliercache.rb
|
85
114
|
- lib/owsensor.rb
|
86
115
|
- lib/saal.rb
|
@@ -92,6 +121,8 @@ files:
|
|
92
121
|
- test/charts_test.rb
|
93
122
|
- test/daemon_test.rb
|
94
123
|
- test/dbstore_test.rb
|
124
|
+
- test/denkovi.json.erb
|
125
|
+
- test/denkovi_test.rb
|
95
126
|
- test/dinrelay.html.erb
|
96
127
|
- test/dinrelay_test.rb
|
97
128
|
- test/nonexistant_sensor.yml
|
@@ -100,38 +131,36 @@ files:
|
|
100
131
|
- test/sensors_test.rb
|
101
132
|
- test/test_charts.yml
|
102
133
|
- test/test_db.yml
|
134
|
+
- test/test_denkovi_sensors.yml
|
103
135
|
- test/test_dinrelay_sensors.yml
|
104
136
|
- test/test_helper.rb
|
105
137
|
- test/test_sensor_cleanups.yml
|
106
138
|
- test/test_sensors.yml
|
107
|
-
- bin/saal_chart~
|
108
|
-
- bin/saal_daemon~
|
109
139
|
homepage: https://github.com/pedrocr/saal
|
110
|
-
licenses:
|
111
|
-
|
140
|
+
licenses:
|
141
|
+
- LGPL-2.1
|
142
|
+
metadata: {}
|
143
|
+
post_install_message:
|
112
144
|
rdoc_options:
|
113
|
-
- -S
|
114
|
-
- -w 2
|
115
|
-
- -N
|
116
|
-
- -c utf8
|
145
|
+
- "-S"
|
146
|
+
- "-w 2"
|
147
|
+
- "-N"
|
148
|
+
- "-c utf8"
|
117
149
|
require_paths:
|
118
150
|
- lib
|
119
151
|
required_ruby_version: !ruby/object:Gem::Requirement
|
120
|
-
none: false
|
121
152
|
requirements:
|
122
|
-
- -
|
153
|
+
- - ">="
|
123
154
|
- !ruby/object:Gem::Version
|
124
155
|
version: '0'
|
125
156
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
|
-
none: false
|
127
157
|
requirements:
|
128
|
-
- -
|
158
|
+
- - ">="
|
129
159
|
- !ruby/object:Gem::Version
|
130
160
|
version: '0'
|
131
161
|
requirements: []
|
132
|
-
|
133
|
-
|
134
|
-
signing_key:
|
162
|
+
rubygems_version: 3.1.2
|
163
|
+
signing_key:
|
135
164
|
specification_version: 2
|
136
165
|
summary: Thin abstraction layer for interfacing and recording sensors (currently onewire)
|
137
166
|
and actuators (currently dinrelay)
|
@@ -141,6 +170,7 @@ test_files:
|
|
141
170
|
- test/charts_test.rb
|
142
171
|
- test/daemon_test.rb
|
143
172
|
- test/dbstore_test.rb
|
173
|
+
- test/denkovi_test.rb
|
144
174
|
- test/dinrelay_test.rb
|
145
175
|
- test/outliercache_test.rb
|
146
176
|
- test/sensor_test.rb
|
data/bin/saal_chart~
DELETED
@@ -1,90 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
NUM_VALUES_SMALL = 500 # Datapoints in "small" charts
|
4
|
-
NUM_VALUES_LARGE = 150 # Datapoints in "large" charts
|
5
|
-
LARGE_CHART_THRESHOLD = 30*24*60*60 # Threshold for a large chart (in seconds)
|
6
|
-
|
7
|
-
require File.dirname(__FILE__)+'/../lib/saal.rb'
|
8
|
-
|
9
|
-
def usage
|
10
|
-
$stderr.puts("Usage: saal_chart <chart dir>")
|
11
|
-
end
|
12
|
-
|
13
|
-
if ARGV.size != 1
|
14
|
-
usage
|
15
|
-
exit (2)
|
16
|
-
end
|
17
|
-
|
18
|
-
SENSOR_RANGES = {:temperature=>[-15, 45], :humidity=>[0,100], :pressure=>[950,1050]}
|
19
|
-
|
20
|
-
|
21
|
-
SAAL::Charts.new.each do |chart|
|
22
|
-
$stderr.puts "Generating chart #{chart.name}"
|
23
|
-
|
24
|
-
pngfile = ARGV[0]+'/chart-'+chart.name.to_s+'.png'
|
25
|
-
ymlfile = ARGV[0]+'/chart-'+chart.name.to_s+'.yml'
|
26
|
-
|
27
|
-
@mins = chart.minimum
|
28
|
-
@maxs = chart.maximum
|
29
|
-
@avgs = chart.average
|
30
|
-
@minmax = {}
|
31
|
-
chart.sensors.each do |s|
|
32
|
-
s = s.name.to_sym
|
33
|
-
@minmax[s] = {:maximum => @maxs[s], :minimum => @mins[s], :average => @avgs[s]}
|
34
|
-
end
|
35
|
-
|
36
|
-
File.open(ymlfile, 'w').write(YAML::dump(@minmax))
|
37
|
-
|
38
|
-
def normalize_data(data, min, max)
|
39
|
-
data.map do |i|
|
40
|
-
if i.nil?
|
41
|
-
-1.0
|
42
|
-
elsif i < min
|
43
|
-
0.0
|
44
|
-
elsif i > max
|
45
|
-
100.0
|
46
|
-
else
|
47
|
-
(((i-min)/(max-min).to_f)*1000).round/10.0
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
@periodnames = chart.periodnames
|
53
|
-
@numperiods = @periodnames.size
|
54
|
-
num_values = ((chart.to-chart.from)>LARGE_CHART_THRESHOLD) ?
|
55
|
-
NUM_VALUES_LARGE :
|
56
|
-
NUM_VALUES_SMALL
|
57
|
-
|
58
|
-
@averages = chart.average(num_values)
|
59
|
-
|
60
|
-
@data = chart.sensors.map do |sensor|
|
61
|
-
normalize_data(@averages[sensor.name.to_sym], *(SENSOR_RANGES[sensor.sensor_type]))
|
62
|
-
end
|
63
|
-
|
64
|
-
@dataurl = @data.map {|values| values.join(",")}.join('|')
|
65
|
-
|
66
|
-
r = {}
|
67
|
-
case chart.alignlabels
|
68
|
-
when :center
|
69
|
-
@periodnamesurl = "||"+@periodnames.join('||')+"||"
|
70
|
-
when :left
|
71
|
-
@periodnamesurl = "|"+@periodnames.join('|')+"||"
|
72
|
-
r[:chxs] = "0,555555,11,-1,lt"
|
73
|
-
end
|
74
|
-
@xincr = 100.0/@numperiods.to_f*10000.truncate.to_f/10000
|
75
|
-
|
76
|
-
r[:chof] = "png"
|
77
|
-
r[:chs] = "700x300"
|
78
|
-
r[:cht] = "lc"
|
79
|
-
r[:chco] = "00ff00,ff0000,0000ff,ff9933,800080"
|
80
|
-
r[:chxt] = "x,y,y,r"
|
81
|
-
r[:chxl] = "0:#{@periodnamesurl}1:|-15ºC||0||15||30||45ºC|2:|0%|25|50|75|100%|3:|950||975||1000||1025||1050 hPa"
|
82
|
-
r[:chg] = "#{@xincr},12.5,1,5"
|
83
|
-
r[:chd] = "t:#{@dataurl}"
|
84
|
-
|
85
|
-
@url = "http://chart.apis.google.com/chart?&"
|
86
|
-
@postdata = r.map{|k,v| k.to_s+"="+v}.join("&")
|
87
|
-
|
88
|
-
|
89
|
-
system "wget --quiet \"#{@url}\" --post-data=\"#{@postdata}\" -O #{pngfile}"
|
90
|
-
end
|
data/bin/saal_daemon~
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
SENSOR_INTERVAL = 60 # seconds between consecutive measurements of the sensors
|
4
|
-
DBCONF = "/etc/saal/database.yml"
|
5
|
-
SENSORSCONF = "/etc/saal/sensors.yml"
|
6
|
-
|
7
|
-
require File.dirname(__FILE__)+'/../lib/saal.rb'
|
8
|
-
|
9
|
-
def usage
|
10
|
-
$stderr.puts "Usage: saal_daemon <pidfile|--foreground>"
|
11
|
-
end
|
12
|
-
|
13
|
-
if ARGV.size != 1
|
14
|
-
usage
|
15
|
-
exit 2
|
16
|
-
else
|
17
|
-
pidfile = ARGV[0]
|
18
|
-
foreground = (ARGV[0] == '--foreground')
|
19
|
-
d = SAAL::Daemon.new(:interval => SENSOR_INTERVAL,
|
20
|
-
:sensorconf => SENSORSCONF,
|
21
|
-
:dbconf => DBCONF,
|
22
|
-
:foreground => foreground,
|
23
|
-
:keep_stdin => true)
|
24
|
-
pid = d.run
|
25
|
-
if !foreground
|
26
|
-
File.open(pidfile, 'w') do |f|
|
27
|
-
f.write(pid)
|
28
|
-
f.close
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|