saal 0.2.24 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/saal_chart +49 -4
- data/bin/saal_denkovi_relays +34 -0
- data/bin/saal_envoy_generate_config +53 -0
- data/bin/saal_envoy_read +144 -0
- data/lib/chart.rb +1 -1
- data/lib/chart_data.rb +1 -1
- data/lib/dbstore.rb +15 -18
- data/lib/denkovi.rb +101 -0
- data/lib/dinrelay.rb +2 -18
- 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/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 +5 -2
- data/test/denkovi.json.erb +39 -0
- data/test/denkovi_test.rb +212 -0
- data/test/dinrelay_test.rb +1 -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/lib/dinrelay.rb
CHANGED
@@ -42,6 +42,7 @@ module SAAL
|
|
42
42
|
@cache_timeout = opts[:cache_timeout] || opts['cache_timeout'] || DEFAULT_CACHE_TIMEOUT
|
43
43
|
@cache = nil
|
44
44
|
@cachehit = nil
|
45
|
+
@cachetime = nil
|
45
46
|
end
|
46
47
|
|
47
48
|
def state(num)
|
@@ -60,25 +61,8 @@ module SAAL
|
|
60
61
|
|
61
62
|
private
|
62
63
|
def do_get(path)
|
63
|
-
|
64
|
-
http = Net::HTTP.new(@host,@port)
|
65
|
-
# Timeout faster when the other side doesn't respond
|
66
|
-
http.open_timeout = @timeout
|
67
|
-
http.read_timeout = @timeout
|
68
|
-
req = Net::HTTP::Get.new(path)
|
69
|
-
req.basic_auth @user, @pass
|
70
|
-
response = http.request(req)
|
71
|
-
if response.code != "200"
|
72
|
-
#$stderr.puts "ERROR: Code #{response.code}"
|
73
|
-
#$stderr.puts response.body
|
74
|
-
return nil
|
75
|
-
end
|
76
|
-
return response
|
77
|
-
rescue Exception
|
78
|
-
return nil
|
79
|
-
end
|
64
|
+
SAAL::do_http_get(@host, @port, path, @user, @pass, @timeout)
|
80
65
|
end
|
81
|
-
|
82
66
|
def parse_index_html(str)
|
83
67
|
doc = Nokogiri::HTML(str)
|
84
68
|
outlets = doc.css('tr[bgcolor="#F4F4F4"]')
|
data/lib/envoy.rb
ADDED
@@ -0,0 +1,287 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module SAAL
|
4
|
+
module Envoy
|
5
|
+
class PowerEnergyUnderlying < SensorUnderlying
|
6
|
+
def initialize(key, production)
|
7
|
+
@key = key
|
8
|
+
@production = production
|
9
|
+
end
|
10
|
+
|
11
|
+
def read(uncached = false)
|
12
|
+
@production.read_val(@key)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class PowerEnergy
|
17
|
+
DEFAULT_HOST = "envoy.local"
|
18
|
+
DEFAULT_TIMEOUT = 2
|
19
|
+
DEFAULT_CACHE_TIMEOUT = 50
|
20
|
+
DEFAULT_SOURCES = [
|
21
|
+
"production_inverters",
|
22
|
+
"production_phase1", "production_phase2", "production_phase3", "production_total",
|
23
|
+
"net_consumption_phase1", "net_consumption_phase2", "net_consumption_phase3", "net_consumption_total",
|
24
|
+
"total_consumption_phase1", "total_consumption_phase2", "total_consumption_phase3", "total_consumption_total",
|
25
|
+
]
|
26
|
+
DEFAULT_TYPES = [
|
27
|
+
"w_now", "wh_lifetime", "va_now", "vah_lifetime",
|
28
|
+
]
|
29
|
+
DEFAULT_PREFIX = "pv"
|
30
|
+
|
31
|
+
def initialize(defs, opts={})
|
32
|
+
@host = defs[:host] || defs['host'] || DEFAULT_HOST
|
33
|
+
@timeout = opts[:timeout] || opts['timeout'] || DEFAULT_TIMEOUT
|
34
|
+
@cache_timeout = opts[:cache_timeout] || opts['cache_timeout'] || DEFAULT_CACHE_TIMEOUT
|
35
|
+
@cache = nil
|
36
|
+
@cachetime = nil
|
37
|
+
@sources = defs[:sources] || defs['source'] || DEFAULT_SOURCES
|
38
|
+
@types = defs[:types] || defs['types'] || DEFAULT_TYPES
|
39
|
+
@prefix = defs[:prefix] || defs['prefix'] || DEFAULT_PREFIX
|
40
|
+
end
|
41
|
+
|
42
|
+
def read_val(name)
|
43
|
+
if !@cachetime or @cachetime < Time.now - @cache_timeout
|
44
|
+
@cache = read_all()
|
45
|
+
@cachetime = Time.now
|
46
|
+
end
|
47
|
+
return @cache ? @cache[name] : nil
|
48
|
+
end
|
49
|
+
|
50
|
+
def create_sensors
|
51
|
+
sensors = {}
|
52
|
+
@sources.product(@types).each do |source, type|
|
53
|
+
key = "#{@prefix}_#{source}_#{type}"
|
54
|
+
sensors[key] = PowerEnergyUnderlying.new(key, self)
|
55
|
+
end
|
56
|
+
sensors
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
def save_vals(dest, name, source)
|
61
|
+
{
|
62
|
+
"wNow" => "w_now",
|
63
|
+
"apprntPwr" => "va_now",
|
64
|
+
"whLifetime" => "wh_lifetime",
|
65
|
+
"vahLifetime" => "vah_lifetime",
|
66
|
+
}.each do |type, label|
|
67
|
+
dest["#{@prefix}_#{name}_#{label}"] = source[type]
|
68
|
+
end
|
69
|
+
|
70
|
+
# Hack around the fact that apprntPwr is broken on the total consumption
|
71
|
+
# calculation for the three-phase sum at least
|
72
|
+
# In those cases it seems to be missing a divide by three, so when the
|
73
|
+
# calculation for voltage and current alone is close do the extra divide
|
74
|
+
va_now = dest["#{@prefix}_#{name}_va_now"]
|
75
|
+
if va_now && !name.include?("phase")
|
76
|
+
voltage = source["rmsVoltage"]
|
77
|
+
current = source["rmsCurrent"]
|
78
|
+
if voltage && current
|
79
|
+
va_alt = voltage * current
|
80
|
+
if ((va_alt / va_now) - 1.0).abs < 0.05
|
81
|
+
dest["#{@prefix}_#{name}_va_now"] = va_now / 3.0
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def read_all
|
88
|
+
response = SAAL::do_http_get(@host, 80, "/production.json?details=1", nil, nil, @timeout)
|
89
|
+
return nil if !response
|
90
|
+
|
91
|
+
values = JSON.parse(response.body)
|
92
|
+
outputs = {}
|
93
|
+
|
94
|
+
values["production"].each do |source|
|
95
|
+
type = source["type"]
|
96
|
+
case type
|
97
|
+
when "inverters"
|
98
|
+
save_vals(outputs, "production_inverters", source)
|
99
|
+
when "eim"
|
100
|
+
if source["lines"]
|
101
|
+
save_vals(outputs, "production_phase1", source["lines"][0])
|
102
|
+
save_vals(outputs, "production_phase2", source["lines"][1])
|
103
|
+
save_vals(outputs, "production_phase3", source["lines"][2])
|
104
|
+
end
|
105
|
+
save_vals(outputs, "production_total", source)
|
106
|
+
else
|
107
|
+
$stderr.puts "WARNING: ENVOY: don't know source type #{type}"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
values["consumption"].each do |source|
|
112
|
+
type = {
|
113
|
+
"total-consumption" => "total",
|
114
|
+
"net-consumption" => "net",
|
115
|
+
}[source["measurementType"]] || "unknown";
|
116
|
+
|
117
|
+
if source["lines"]
|
118
|
+
save_vals(outputs, "#{type}_consumption_phase1", source["lines"][0])
|
119
|
+
save_vals(outputs, "#{type}_consumption_phase2", source["lines"][1])
|
120
|
+
save_vals(outputs, "#{type}_consumption_phase3", source["lines"][2])
|
121
|
+
end
|
122
|
+
save_vals(outputs, "#{type}_consumption_total", source)
|
123
|
+
end
|
124
|
+
|
125
|
+
outputs
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
class ACQualityUnderlying < SensorUnderlying
|
130
|
+
def initialize(key, production)
|
131
|
+
@key = key
|
132
|
+
@production = production
|
133
|
+
end
|
134
|
+
|
135
|
+
def read(uncached = false)
|
136
|
+
@production.read_val(@key)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class ACQuality
|
141
|
+
DEFAULT_HOST = "envoy.local"
|
142
|
+
DEFAULT_TIMEOUT = 2
|
143
|
+
DEFAULT_CACHE_TIMEOUT = 50
|
144
|
+
DEFAULT_SOURCES = ["total","phase1","phase2","phase3",]
|
145
|
+
DEFAULT_TYPES = ["frequency","voltage"]
|
146
|
+
DEFAULT_PREFIX = "ac"
|
147
|
+
|
148
|
+
def initialize(defs, opts={})
|
149
|
+
@host = defs[:host] || defs['host'] || DEFAULT_HOST
|
150
|
+
@timeout = opts[:timeout] || opts['timeout'] || DEFAULT_TIMEOUT
|
151
|
+
@cache_timeout = opts[:cache_timeout] || opts['cache_timeout'] || DEFAULT_CACHE_TIMEOUT
|
152
|
+
@cache = nil
|
153
|
+
@cachetime = nil
|
154
|
+
@sources = defs[:sources] || defs['source'] || DEFAULT_SOURCES
|
155
|
+
@types = defs[:types] || defs['types'] || DEFAULT_TYPES
|
156
|
+
@prefix = defs[:prefix] || defs['prefix'] || DEFAULT_PREFIX
|
157
|
+
end
|
158
|
+
|
159
|
+
def read_val(name)
|
160
|
+
if !@cachetime or @cachetime < Time.now - @cache_timeout
|
161
|
+
@cache = read_all()
|
162
|
+
@cachetime = Time.now
|
163
|
+
end
|
164
|
+
return @cache ? @cache[name] : nil
|
165
|
+
end
|
166
|
+
|
167
|
+
def create_sensors
|
168
|
+
sensors = {}
|
169
|
+
@sources.product(@types).each do |source, type|
|
170
|
+
key = "#{@prefix}_#{source}_#{type}"
|
171
|
+
sensors[key] = ACQualityUnderlying.new(key, self)
|
172
|
+
end
|
173
|
+
sensors
|
174
|
+
end
|
175
|
+
|
176
|
+
private
|
177
|
+
def save_vals(dest, name, source)
|
178
|
+
{
|
179
|
+
"voltage" => "voltage",
|
180
|
+
"freq" => "frequency",
|
181
|
+
}.each do |type, label|
|
182
|
+
dest["#{@prefix}_#{name}_#{label}"] = source[type]
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def read_all
|
187
|
+
response = SAAL::do_http_get(@host, 80, "/ivp/meters/readings", nil, nil, @timeout)
|
188
|
+
return nil if !response
|
189
|
+
|
190
|
+
values = JSON.parse(response.body)
|
191
|
+
outputs = {}
|
192
|
+
source = values[0]
|
193
|
+
save_vals(outputs, "total", source)
|
194
|
+
if source["channels"]
|
195
|
+
save_vals(outputs, "phase1", source["channels"][0])
|
196
|
+
save_vals(outputs, "phase2", source["channels"][1])
|
197
|
+
save_vals(outputs, "phase3", source["channels"][2])
|
198
|
+
end
|
199
|
+
|
200
|
+
outputs
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
class InverterUnderlying < SensorUnderlying
|
205
|
+
def initialize(key, inverters)
|
206
|
+
@key = key
|
207
|
+
@inverters = inverters
|
208
|
+
end
|
209
|
+
|
210
|
+
def read(uncached = false)
|
211
|
+
@inverters.read_val(@key)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
class Inverters
|
216
|
+
DEFAULT_TIMEOUT = 2
|
217
|
+
DEFAULT_CACHE_TIMEOUT = 50
|
218
|
+
DEFAULT_SOURCES = []
|
219
|
+
DEFAULT_TYPES = ["w_now"] # "last_report_date", "w_max"
|
220
|
+
DEFAULT_USER = nil
|
221
|
+
DEFAULT_PASSWORD = nil
|
222
|
+
DEFAULT_PREFIX = "inverters"
|
223
|
+
attr_reader :inverters
|
224
|
+
|
225
|
+
def initialize(defs, opts={})
|
226
|
+
@host = defs[:host] || defs['host'] || DEFAULT_HOST
|
227
|
+
@user = defs[:user] || defs['user'] || DEFAULT_USER
|
228
|
+
@password = defs[:password] || defs['password'] || DEFAULT_PASSWORD
|
229
|
+
@timeout = opts[:timeout] || opts['timeout'] || DEFAULT_TIMEOUT
|
230
|
+
@cache_timeout = opts[:cache_timeout] || opts['cache_timeout'] || DEFAULT_CACHE_TIMEOUT
|
231
|
+
@cache = nil
|
232
|
+
@cachetime = nil
|
233
|
+
@inverters_list = {}
|
234
|
+
@inverters = defs[:inverters] || defs['inverters'] || DEFAULT_SOURCES
|
235
|
+
@types = defs[:types] || defs['types'] || DEFAULT_TYPES
|
236
|
+
@prefix = defs[:prefix] || defs['prefix'] || DEFAULT_PREFIX
|
237
|
+
end
|
238
|
+
|
239
|
+
def read_val(name)
|
240
|
+
if !@cachetime or @cachetime < Time.now - @cache_timeout
|
241
|
+
@cache = read_all()
|
242
|
+
@cachetime = Time.now
|
243
|
+
end
|
244
|
+
return @cache ? @cache[name] : nil
|
245
|
+
end
|
246
|
+
|
247
|
+
def enumerate
|
248
|
+
read_val("foo") # Force a read to make sure the inverter serials are stored
|
249
|
+
@inverters_list.keys
|
250
|
+
end
|
251
|
+
|
252
|
+
def set_all_inverters!
|
253
|
+
@inverters = self.enumerate
|
254
|
+
end
|
255
|
+
|
256
|
+
def create_sensors
|
257
|
+
sensors = {}
|
258
|
+
@inverters.product(@types).each do |source, type|
|
259
|
+
key = "#{@prefix}_#{source}_#{type}"
|
260
|
+
sensors[key] = InverterUnderlying.new(key, self)
|
261
|
+
end
|
262
|
+
sensors
|
263
|
+
end
|
264
|
+
|
265
|
+
private
|
266
|
+
def read_all
|
267
|
+
response = SAAL::do_http_get_digest(@host, 80, "/api/v1/production/inverters", @user, @password, @timeout)
|
268
|
+
return nil if !response
|
269
|
+
|
270
|
+
values = JSON.parse(response.body)
|
271
|
+
inverters = {}
|
272
|
+
values.each do |inverter|
|
273
|
+
serial = inverter["serialNumber"]
|
274
|
+
@inverters_list[serial] = true
|
275
|
+
{"lastReportDate" => "last_report_date",
|
276
|
+
"lastReportWatts" => "w_now",
|
277
|
+
"maxReportWatts" => "w_max",
|
278
|
+
}.each do |type, label|
|
279
|
+
inverters["#{@prefix}_#{serial}_#{label}"] = inverter[type]
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
inverters
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
data/lib/http.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'net/http/digest_auth'
|
4
|
+
|
5
|
+
def SAAL::do_http_get(host, port, path, user, pass, timeout)
|
6
|
+
begin
|
7
|
+
http = Net::HTTP.new(host,port)
|
8
|
+
# Timeout faster when the other side doesn't respond
|
9
|
+
http.open_timeout = timeout
|
10
|
+
http.read_timeout = timeout
|
11
|
+
req = Net::HTTP::Get.new(path)
|
12
|
+
req.basic_auth(user, pass) if user && pass
|
13
|
+
response = http.request(req)
|
14
|
+
if response.code != "200"
|
15
|
+
#$stderr.puts "ERROR: Code #{response.code}"
|
16
|
+
#$stderr.puts response.body
|
17
|
+
return nil
|
18
|
+
end
|
19
|
+
return response
|
20
|
+
rescue Exception
|
21
|
+
return nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def SAAL::do_http_get_digest(host, port, path, user, pass, timeout)
|
26
|
+
begin
|
27
|
+
uri = URI.parse "http://#{host}:#{port}/#{path}"
|
28
|
+
digest_auth = Net::HTTP::DigestAuth.new
|
29
|
+
uri.user = user
|
30
|
+
uri.password = pass
|
31
|
+
http = Net::HTTP.new(host,port)
|
32
|
+
# Timeout faster when the other side doesn't respond
|
33
|
+
http.open_timeout = timeout
|
34
|
+
http.read_timeout = timeout
|
35
|
+
req = Net::HTTP::Get.new(path)
|
36
|
+
response = http.request(req)
|
37
|
+
if response.code == "401" && user && pass
|
38
|
+
auth = digest_auth.auth_header uri, response['www-authenticate'], 'GET'
|
39
|
+
req.add_field 'Authorization', auth
|
40
|
+
response = http.request(req)
|
41
|
+
end
|
42
|
+
if response.code != "200"
|
43
|
+
#$stderr.puts "ERROR: Code #{response.code}"
|
44
|
+
#$stderr.puts response.body
|
45
|
+
return nil
|
46
|
+
end
|
47
|
+
return response
|
48
|
+
rescue Exception
|
49
|
+
return nil
|
50
|
+
end
|
51
|
+
end
|
data/lib/outliercache.rb
CHANGED
@@ -41,7 +41,7 @@ module SAAL
|
|
41
41
|
def valid_cache
|
42
42
|
@compcache.sort!
|
43
43
|
central = @compcache[1..(@compcache.size-2)]
|
44
|
-
sum = central.inject(0.0){|
|
44
|
+
sum = central.inject(0.0){|csum,el| csum+el}
|
45
45
|
return false if sum == 0.0
|
46
46
|
average = sum/central.size
|
47
47
|
central.each do |el|
|
data/lib/saal.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'yaml'
|
2
|
-
require "
|
2
|
+
require "mysql2"
|
3
3
|
require 'ownet'
|
4
4
|
require 'nokogiri'
|
5
5
|
require 'erb'
|
@@ -10,7 +10,7 @@ module SAAL
|
|
10
10
|
DBCONF = CONFDIR+"database.yml"
|
11
11
|
CHARTSCONF = CONFDIR+"charts.yml"
|
12
12
|
|
13
|
-
VERSION = '0.
|
13
|
+
VERSION = '0.3.3'
|
14
14
|
end
|
15
15
|
|
16
16
|
require File.dirname(__FILE__)+'/dbstore.rb'
|
@@ -23,4 +23,7 @@ require File.dirname(__FILE__)+'/chart.rb'
|
|
23
23
|
require File.dirname(__FILE__)+'/chart_data.rb'
|
24
24
|
require File.dirname(__FILE__)+'/outliercache.rb'
|
25
25
|
require File.dirname(__FILE__)+'/dinrelay.rb'
|
26
|
+
require File.dirname(__FILE__)+'/envoy.rb'
|
27
|
+
require File.dirname(__FILE__)+'/http.rb'
|
28
|
+
require File.dirname(__FILE__)+'/denkovi.rb'
|
26
29
|
|
data/lib/sensors.rb
CHANGED
@@ -40,9 +40,38 @@ module SAAL
|
|
40
40
|
defs.merge!('name' => outlet_descriptions[num])
|
41
41
|
Sensor.new(dbstore, oname, DINRelay::Outlet.new(num.to_i, og), defs, opts)
|
42
42
|
end
|
43
|
+
elsif defs['envoy_power_energy']
|
44
|
+
defs = defs['envoy_power_energy'].merge('prefix' => name)
|
45
|
+
pe = SAAL::Envoy::PowerEnergy::new(defs)
|
46
|
+
sensors = pe.create_sensors
|
47
|
+
return sensors.map do |name, underlying|
|
48
|
+
Sensor.new(dbstore, name, underlying, defs, opts)
|
49
|
+
end
|
50
|
+
elsif defs['envoy_ac_quality']
|
51
|
+
defs = defs['envoy_ac_quality'].merge('prefix' => name)
|
52
|
+
pe = SAAL::Envoy::ACQuality::new(defs)
|
53
|
+
sensors = pe.create_sensors
|
54
|
+
return sensors.map do |name, underlying|
|
55
|
+
Sensor.new(dbstore, name, underlying, defs, opts)
|
56
|
+
end
|
57
|
+
elsif defs['envoy_inverters']
|
58
|
+
defs = defs['envoy_inverters'].merge('prefix' => name)
|
59
|
+
pe = SAAL::Envoy::Inverters::new(defs)
|
60
|
+
sensors = pe.create_sensors
|
61
|
+
return sensors.map do |name, underlying|
|
62
|
+
Sensor.new(dbstore, name, underlying, defs, opts)
|
63
|
+
end
|
64
|
+
elsif defs['denkovi']
|
65
|
+
defs = defs['denkovi'].merge('prefix' => name)
|
66
|
+
denkovi = SAAL::Denkovi::OutletGroup::new(defs)
|
67
|
+
sensors = denkovi.create_sensors
|
68
|
+
return sensors.map do |name, vals|
|
69
|
+
underlying, description = vals
|
70
|
+
defs.merge!('name' => description)
|
71
|
+
Sensor.new(dbstore, name, underlying, defs, opts)
|
72
|
+
end
|
43
73
|
else
|
44
|
-
|
45
|
-
"from the configuration for #{name}"
|
74
|
+
$stderror.puts "WARNING: Couldn't figure out a valid sensor type for #{name}"
|
46
75
|
end
|
47
76
|
end
|
48
77
|
end
|
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.
|
10
|
-
s.date = '
|
9
|
+
s.version = '0.3.3'
|
10
|
+
s.date = '2020-12-28'
|
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
|
@@ -19,6 +19,7 @@ EOF
|
|
19
19
|
s.authors = ["Pedro Côrte-Real"]
|
20
20
|
s.email = 'pedro@pedrocr.net'
|
21
21
|
s.homepage = 'https://github.com/pedrocr/saal'
|
22
|
+
s.licenses = 'LGPL-2.1'
|
22
23
|
|
23
24
|
s.require_paths = %w[lib]
|
24
25
|
|
@@ -28,9 +29,10 @@ EOF
|
|
28
29
|
|
29
30
|
s.executables = Dir.glob("bin/*").map{|f| f.gsub('bin/','')}
|
30
31
|
|
31
|
-
s.
|
32
|
-
s.
|
33
|
-
s.
|
32
|
+
s.add_runtime_dependency 'ownet', "~>0.2"
|
33
|
+
s.add_runtime_dependency 'mysql2', "~>0.5"
|
34
|
+
s.add_runtime_dependency 'nokogiri', '~>1.8'
|
35
|
+
s.add_runtime_dependency 'net-http-digest_auth', '~>1.4'
|
34
36
|
|
35
37
|
# = MANIFEST =
|
36
38
|
s.files = %w[
|
@@ -43,7 +45,10 @@ EOF
|
|
43
45
|
bin/dinrelaystatus
|
44
46
|
bin/saal_chart
|
45
47
|
bin/saal_daemon
|
48
|
+
bin/saal_denkovi_relays
|
46
49
|
bin/saal_dump_database
|
50
|
+
bin/saal_envoy_generate_config
|
51
|
+
bin/saal_envoy_read
|
47
52
|
bin/saal_import_mysql
|
48
53
|
bin/saal_readall
|
49
54
|
lib/chart.rb
|
@@ -51,7 +56,10 @@ EOF
|
|
51
56
|
lib/charts.rb
|
52
57
|
lib/daemon.rb
|
53
58
|
lib/dbstore.rb
|
59
|
+
lib/denkovi.rb
|
54
60
|
lib/dinrelay.rb
|
61
|
+
lib/envoy.rb
|
62
|
+
lib/http.rb
|
55
63
|
lib/outliercache.rb
|
56
64
|
lib/owsensor.rb
|
57
65
|
lib/saal.rb
|
@@ -63,6 +71,8 @@ EOF
|
|
63
71
|
test/charts_test.rb
|
64
72
|
test/daemon_test.rb
|
65
73
|
test/dbstore_test.rb
|
74
|
+
test/denkovi.json.erb
|
75
|
+
test/denkovi_test.rb
|
66
76
|
test/dinrelay.html.erb
|
67
77
|
test/dinrelay_test.rb
|
68
78
|
test/nonexistant_sensor.yml
|
@@ -71,6 +81,7 @@ EOF
|
|
71
81
|
test/sensors_test.rb
|
72
82
|
test/test_charts.yml
|
73
83
|
test/test_db.yml
|
84
|
+
test/test_denkovi_sensors.yml
|
74
85
|
test/test_dinrelay_sensors.yml
|
75
86
|
test/test_helper.rb
|
76
87
|
test/test_sensor_cleanups.yml
|