saal 0.3.3 → 0.3.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 90aa53b1093427163af28bee630532e79ccefea47de44463641c3e387f038640
4
- data.tar.gz: 41fca314cb32d91ca10bfb1982cf7e60a6b584c3c521b8ddcd148b18f465fd86
3
+ metadata.gz: '097e00e7d501d49e8b411d07a6a7eff6afe0adf220c3e1757304428c4cc059f1'
4
+ data.tar.gz: 398f11226d5a182aa92417448afd7b3adf0e6a3d1ab120b8f903eb952e6c131b
5
5
  SHA512:
6
- metadata.gz: ff26de3ff3cca4750a365b9672a82165d449f7c11fb3bd57d7f3f27758636a521d766ae99dc84b50cd30e940453eb30826ad485e44f9e50d723bb5625cd07915
7
- data.tar.gz: f93e18eacc3a2eb6555c95b9ea91f74506a39af91c6083ab6dbb3acc1ef2d83387db9ed59a573afcb7bbd1354cfdf7af51ec11122d9f48f287baf273c235debf
6
+ metadata.gz: ce014accc32521fb1fad84ed552fe92d6ed3798aef83b30769b03244703d80c205d5463c5ebf9b5ad0fff418663d3293add9291d7344b51db4201a634ee0308e
7
+ data.tar.gz: 3aaeb5d0825733dd3e87d4eb9fb9900f6f7cb5a78c9be3a8168ba7b7afef7ce379d51d8e4a267c59f1fcce86e33075c6a55eb18cfcba65932d138d718f534dd0
data/bin/saal_envoy_read CHANGED
@@ -31,6 +31,14 @@ def fdisp_dec(val)
31
31
  end
32
32
  end
33
33
 
34
+ def fdispd(val)
35
+ if val
36
+ Time.at(val.to_i).strftime("%Y-%m-%d %k:%M:%S")
37
+ else
38
+ "n/a"
39
+ end
40
+ end
41
+
34
42
  def l(vals, name)
35
43
  sensor = vals[name]
36
44
  if sensor
@@ -137,7 +145,7 @@ inverters = envoy.create_sensors
137
145
  puts " Found #{envoy.inverters.size} inverters"
138
146
  envoy.inverters.each do |serial|
139
147
  puts " INVERTER: #{serial} \
140
- date:#{l(inverters,"inverters_#{serial}_last_report_date")} \
148
+ date:#{fdispd(l(inverters,"inverters_#{serial}_last_report_date"))} \
141
149
  lastWatts:#{l(inverters,"inverters_#{serial}_w_now")} \
142
150
  maxWatts:#{l(inverters,"inverters_#{serial}_w_max")} \
143
151
  "
data/lib/dbstore.rb CHANGED
@@ -35,6 +35,32 @@ module SAAL
35
35
  db_range("AVG", sensor, from, to)
36
36
  end
37
37
 
38
+ def weighted_average(sensor, from, to)
39
+ total_time = 0
40
+ total_value = 0.0
41
+ previous_value = nil
42
+ start_time = nil
43
+ initialized = false
44
+ db_query "SELECT date,value FROM sensor_reads
45
+ WHERE sensor = '#{db_quote(sensor.to_s)}'
46
+ AND date >= #{from.to_s}
47
+ AND date <= #{to.to_s}" do |r|
48
+ r.each do |row|
49
+ date = row["date"].to_i
50
+ value = row["value"].to_f
51
+ if start_time
52
+ elapsed = date - start_time
53
+ total_value += elapsed * previous_value
54
+ total_time += elapsed
55
+ initialized = true
56
+ end
57
+ start_time = date
58
+ previous_value = value
59
+ end
60
+ end
61
+ initialized ? total_value / total_time : nil
62
+ end
63
+
38
64
  def minimum(sensor, from, to)
39
65
  db_range("MIN", sensor, from, to)
40
66
  end
data/lib/denkovi.rb CHANGED
@@ -30,7 +30,7 @@ module SAAL
30
30
 
31
31
  class OutletGroup
32
32
  DEFAULT_TIMEOUT = 2
33
- DEFAULT_CACHE_TIMEOUT = 60
33
+ DEFAULT_CACHE_TIMEOUT = 5
34
34
  DEFAULT_OUTLETS = {}
35
35
  DEFAULT_DESCRIPTIONS = {}
36
36
 
data/lib/dinrelay.rb CHANGED
@@ -29,7 +29,7 @@ module SAAL
29
29
 
30
30
  class OutletGroup
31
31
  DEFAULT_TIMEOUT = 2
32
- DEFAULT_CACHE_TIMEOUT = 60
32
+ DEFAULT_CACHE_TIMEOUT = 5
33
33
 
34
34
  attr_accessor :host, :port, :user, :pass, :timeout, :cache_timeout
35
35
 
data/lib/envoy.rb CHANGED
@@ -15,8 +15,9 @@ module SAAL
15
15
 
16
16
  class PowerEnergy
17
17
  DEFAULT_HOST = "envoy.local"
18
+ DEFAULT_TOKEN = ""
18
19
  DEFAULT_TIMEOUT = 2
19
- DEFAULT_CACHE_TIMEOUT = 50
20
+ DEFAULT_CACHE_TIMEOUT = 5
20
21
  DEFAULT_SOURCES = [
21
22
  "production_inverters",
22
23
  "production_phase1", "production_phase2", "production_phase3", "production_total",
@@ -30,6 +31,7 @@ module SAAL
30
31
 
31
32
  def initialize(defs, opts={})
32
33
  @host = defs[:host] || defs['host'] || DEFAULT_HOST
34
+ @token = defs[:token] || defs['token'] || DEFAULT_TOKEN
33
35
  @timeout = opts[:timeout] || opts['timeout'] || DEFAULT_TIMEOUT
34
36
  @cache_timeout = opts[:cache_timeout] || opts['cache_timeout'] || DEFAULT_CACHE_TIMEOUT
35
37
  @cache = nil
@@ -85,7 +87,7 @@ module SAAL
85
87
  end
86
88
 
87
89
  def read_all
88
- response = SAAL::do_http_get(@host, 80, "/production.json?details=1", nil, nil, @timeout)
90
+ response = SAAL::do_https_get_token(@host, "/production.json?details=1", @token, @timeout)
89
91
  return nil if !response
90
92
 
91
93
  values = JSON.parse(response.body)
@@ -139,14 +141,16 @@ module SAAL
139
141
 
140
142
  class ACQuality
141
143
  DEFAULT_HOST = "envoy.local"
144
+ DEFAULT_TOKEN = ""
142
145
  DEFAULT_TIMEOUT = 2
143
- DEFAULT_CACHE_TIMEOUT = 50
146
+ DEFAULT_CACHE_TIMEOUT = 5
144
147
  DEFAULT_SOURCES = ["total","phase1","phase2","phase3",]
145
148
  DEFAULT_TYPES = ["frequency","voltage"]
146
149
  DEFAULT_PREFIX = "ac"
147
150
 
148
151
  def initialize(defs, opts={})
149
152
  @host = defs[:host] || defs['host'] || DEFAULT_HOST
153
+ @token = defs[:token] || defs['token'] || DEFAULT_TOKEN
150
154
  @timeout = opts[:timeout] || opts['timeout'] || DEFAULT_TIMEOUT
151
155
  @cache_timeout = opts[:cache_timeout] || opts['cache_timeout'] || DEFAULT_CACHE_TIMEOUT
152
156
  @cache = nil
@@ -184,7 +188,7 @@ module SAAL
184
188
  end
185
189
 
186
190
  def read_all
187
- response = SAAL::do_http_get(@host, 80, "/ivp/meters/readings", nil, nil, @timeout)
191
+ response = SAAL::do_https_get_token(@host, "/ivp/meters/readings", @token, @timeout)
188
192
  return nil if !response
189
193
 
190
194
  values = JSON.parse(response.body)
@@ -213,19 +217,18 @@ module SAAL
213
217
  end
214
218
 
215
219
  class Inverters
220
+ DEFAULT_HOST = "envoy.local"
221
+ DEFAULT_TOKEN = nil
216
222
  DEFAULT_TIMEOUT = 2
217
223
  DEFAULT_CACHE_TIMEOUT = 50
218
224
  DEFAULT_SOURCES = []
219
225
  DEFAULT_TYPES = ["w_now"] # "last_report_date", "w_max"
220
- DEFAULT_USER = nil
221
- DEFAULT_PASSWORD = nil
222
226
  DEFAULT_PREFIX = "inverters"
223
227
  attr_reader :inverters
224
228
 
225
229
  def initialize(defs, opts={})
226
230
  @host = defs[:host] || defs['host'] || DEFAULT_HOST
227
- @user = defs[:user] || defs['user'] || DEFAULT_USER
228
- @password = defs[:password] || defs['password'] || DEFAULT_PASSWORD
231
+ @token = defs[:token] || defs['token'] || DEFAULT_TOKEN
229
232
  @timeout = opts[:timeout] || opts['timeout'] || DEFAULT_TIMEOUT
230
233
  @cache_timeout = opts[:cache_timeout] || opts['cache_timeout'] || DEFAULT_CACHE_TIMEOUT
231
234
  @cache = nil
@@ -264,7 +267,7 @@ module SAAL
264
267
 
265
268
  private
266
269
  def read_all
267
- response = SAAL::do_http_get_digest(@host, 80, "/api/v1/production/inverters", @user, @password, @timeout)
270
+ response = SAAL::do_https_get_token(@host, "/api/v1/production/inverters", @token, @timeout)
268
271
  return nil if !response
269
272
 
270
273
  values = JSON.parse(response.body)
data/lib/http.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'uri'
2
2
  require 'net/http'
3
- require 'net/http/digest_auth'
3
+ require 'openssl'
4
4
 
5
5
  def SAAL::do_http_get(host, port, path, user, pass, timeout)
6
6
  begin
@@ -22,26 +22,21 @@ def SAAL::do_http_get(host, port, path, user, pass, timeout)
22
22
  end
23
23
  end
24
24
 
25
- def SAAL::do_http_get_digest(host, port, path, user, pass, timeout)
25
+ def SAAL::do_https_get_token(host, path, token, timeout)
26
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)
27
+ http = Net::HTTP.new(host,443)
32
28
  # Timeout faster when the other side doesn't respond
33
29
  http.open_timeout = timeout
34
30
  http.read_timeout = timeout
31
+ http.use_ssl = true
32
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
35
33
  req = Net::HTTP::Get.new(path)
34
+ req['Accept'] = "application/json"
35
+ req['Authorization'] = "Bearer #{token}"
36
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
37
  if response.code != "200"
43
- #$stderr.puts "ERROR: Code #{response.code}"
44
- #$stderr.puts response.body
38
+ $stderr.puts "ERROR: Code #{response.code}"
39
+ $stderr.puts response.body
45
40
  return nil
46
41
  end
47
42
  return response
data/lib/saal.rb CHANGED
@@ -10,7 +10,7 @@ module SAAL
10
10
  DBCONF = CONFDIR+"database.yml"
11
11
  CHARTSCONF = CONFDIR+"charts.yml"
12
12
 
13
- VERSION = '0.3.3'
13
+ VERSION = '0.3.5'
14
14
  end
15
15
 
16
16
  require File.dirname(__FILE__)+'/dbstore.rb'
data/lib/sensor.rb CHANGED
@@ -72,6 +72,11 @@ module SAAL
72
72
  apply_offset @dbstore.average(@name, from, to)
73
73
  end
74
74
 
75
+ def weighted_average(from, to)
76
+ return @mock_opts[:weighted_average] if @mock_opts[:weighted_average]
77
+ apply_offset @dbstore.weighted_average(@name, from, to)
78
+ end
79
+
75
80
  def minimum(from, to)
76
81
  return @mock_opts[:minimum] if @mock_opts[:minimum]
77
82
  apply_offset @dbstore.minimum(@name, from, to)
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.3.3'
10
- s.date = '2020-12-28'
9
+ s.version = '0.3.5'
10
+ s.date = '2024-02-08'
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/dbstore_test.rb CHANGED
@@ -42,6 +42,21 @@ class TestFileStore < Test::Unit::TestCase
42
42
  assert_nil @dbstore.average(:test_sensor, 50, 60)
43
43
  end
44
44
 
45
+ def test_weighted_average
46
+ db_setup
47
+ test_values = [[10, 7.323],[12, 5.432],[23, -2.125], [44, 0.123]]
48
+ test_average = ((12-10)*7.323+(23-12)*5.432+(44-23)*(-2.125)) / (44-10)
49
+ test_values.each do |values|
50
+ @dbstore.write(:test_sensor, *values)
51
+ end
52
+
53
+ assert_instance_of Float, @dbstore.average(:test_sensor, 10, 44)
54
+ assert_in_delta test_average, @dbstore.weighted_average(:test_sensor, 10, 44), 0.001
55
+
56
+ # when there are no points it's nil
57
+ assert_nil @dbstore.weighted_average(:test_sensor, 50, 60)
58
+ end
59
+
45
60
  def test_min_max
46
61
  db_setup
47
62
  test_values = [[10, 7.323],[12, 5.432],[23, -2.125], [44, 0.123]]
data/test/sensor_test.rb CHANGED
@@ -31,6 +31,9 @@ class MockDBStore
31
31
  def average(sensor, from, to)
32
32
  @value
33
33
  end
34
+ def weighted_average(sensor, from, to)
35
+ @value
36
+ end
34
37
  def minimum(sensor, from, to)
35
38
  @value
36
39
  end
@@ -112,6 +115,7 @@ class TestSensor < Test::Unit::TestCase
112
115
  assert_equal corrected, sensor.minimum(0,100)
113
116
  assert_equal corrected, sensor.maximum(0,100)
114
117
  assert_equal corrected, sensor.average(0,100)
118
+ assert_equal corrected, sensor.weighted_average(0,100)
115
119
  end
116
120
 
117
121
  def test_linear_correction
@@ -125,6 +129,7 @@ class TestSensor < Test::Unit::TestCase
125
129
  assert_equal corrected, sensor.minimum(0,100)
126
130
  assert_equal corrected, sensor.maximum(0,100)
127
131
  assert_equal corrected, sensor.average(0,100)
132
+ assert_equal corrected, sensor.weighted_average(0,100)
128
133
  end
129
134
 
130
135
  def test_sensor_type
@@ -145,9 +150,10 @@ class TestSensor < Test::Unit::TestCase
145
150
  assert_equal 2.0, @mockable.read
146
151
  @mockable.write(3.0)
147
152
  assert_equal 3.0, @mockable.read
148
- @mockable.mock_set(:minimum => 1.0, :average => 2.0, :maximum => 3.0, :last_value => 5.0)
153
+ @mockable.mock_set(:minimum => 1.0, :average => 2.0, :weighted_average => 2.5, :maximum => 3.0, :last_value => 5.0)
149
154
  assert_equal 1.0, @mockable.minimum(0,100)
150
155
  assert_equal 2.0, @mockable.average(0,100)
156
+ assert_equal 2.5, @mockable.weighted_average(0,100)
151
157
  assert_equal 3.0, @mockable.maximum(0,100)
152
158
  assert_equal 5.0, @mockable.last_value
153
159
  assert_equal 3.0, @mockable.read
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: saal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pedro Côrte-Real
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-28 00:00:00.000000000 Z
11
+ date: 2024-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ownet
@@ -71,16 +71,16 @@ description: "A daemon and libraries to create an abstraction layer that interfa
71
71
  current and historical values, and allowing changes of state.\n"
72
72
  email: pedro@pedrocr.net
73
73
  executables:
74
- - dinrelaystatus
75
74
  - dinrelayset
76
- - saal_import_mysql
77
- - saal_dump_database
78
- - saal_readall
79
- - saal_denkovi_relays
75
+ - dinrelaystatus
80
76
  - saal_chart
81
77
  - saal_daemon
78
+ - saal_denkovi_relays
79
+ - saal_dump_database
82
80
  - saal_envoy_generate_config
83
81
  - saal_envoy_read
82
+ - saal_import_mysql
83
+ - saal_readall
84
84
  extensions: []
85
85
  extra_rdoc_files:
86
86
  - README.rdoc
@@ -140,7 +140,7 @@ homepage: https://github.com/pedrocr/saal
140
140
  licenses:
141
141
  - LGPL-2.1
142
142
  metadata: {}
143
- post_install_message:
143
+ post_install_message:
144
144
  rdoc_options:
145
145
  - "-S"
146
146
  - "-w 2"
@@ -159,8 +159,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
159
159
  - !ruby/object:Gem::Version
160
160
  version: '0'
161
161
  requirements: []
162
- rubygems_version: 3.1.2
163
- signing_key:
162
+ rubygems_version: 3.3.5
163
+ signing_key:
164
164
  specification_version: 2
165
165
  summary: Thin abstraction layer for interfacing and recording sensors (currently onewire)
166
166
  and actuators (currently dinrelay)