senec 0.10.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/push.yml +1 -1
- data/.rubocop.yml +1 -1
- data/Gemfile +0 -3
- data/README.md +8 -6
- data/lib/senec/connection.rb +30 -0
- data/lib/senec/request.rb +31 -19
- data/lib/senec/state.rb +21 -17
- data/lib/senec/version.rb +1 -1
- data/lib/senec.rb +1 -0
- data/senec.gemspec +4 -2
- metadata +33 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0d619a385d96958f3d69b8486977b64ec6c0d758dff3179138714ba22f7915d5
|
4
|
+
data.tar.gz: 52991e9de034ebeda649ebf48f138d9f3dc71d69d005e25d8e45bcac2bd79804
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: af0afea0cbee005eb14a502cc065c8218b5e61ad466c30c32ce9cc912fea3de7471b1c39ae8feef66b29d64af5b63015ae4833e40065157e3fdc67ac141431ad
|
7
|
+
data.tar.gz: 60ecf0d725aa18fa9f80e94cfce90ae164d0118b468b128ec2a8ac5f312cdc578d22d2a8e0f7c12ce9d7b5a08c6dd37aca4de917018fc5806ef0d12c75c9d5e8
|
data/.github/workflows/push.yml
CHANGED
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
@@ -23,6 +23,3 @@ gem 'rubocop-rake'
|
|
23
23
|
|
24
24
|
# Record your test suite's HTTP interactions and replay them during future test runs for fast, deterministic, accurate tests. (https://relishapp.com/vcr/vcr/docs)
|
25
25
|
gem 'vcr'
|
26
|
-
|
27
|
-
# Library for stubbing HTTP requests in Ruby. (https://github.com/bblimke/webmock)
|
28
|
-
gem 'webmock'
|
data/README.md
CHANGED
@@ -23,8 +23,8 @@ $ gem install senec
|
|
23
23
|
```ruby
|
24
24
|
require 'senec'
|
25
25
|
|
26
|
-
|
27
|
-
request = Senec::Request.new
|
26
|
+
connection = Senec::Connection.new(host: '192.168.178.123', schema: 'https')
|
27
|
+
request = Senec::Request.new(connection:)
|
28
28
|
|
29
29
|
puts "PV production: #{request.inverter_power} W"
|
30
30
|
puts "House power consumption: #{request.house_power} W"
|
@@ -61,17 +61,19 @@ puts "Measure time: #{Time.at request.measure_time}"
|
|
61
61
|
# Measure time: 2021-10-06 17:50:22 +0200
|
62
62
|
```
|
63
63
|
|
64
|
-
To get the state name (in German) instead of just the number:
|
64
|
+
To get the state name (in English, German or Italian) instead of just the number:
|
65
65
|
|
66
66
|
```ruby
|
67
|
-
|
68
|
-
|
67
|
+
# Get a Hash with all available state names:
|
68
|
+
state_names = Senec::State.new(connection:).names(language: :de) # or :en or :it
|
69
|
+
# Use this hash for the number => string mapping:
|
70
|
+
request = Senec::Request.new(connection:, state_names:)
|
69
71
|
|
70
72
|
puts request.current_state_name
|
71
73
|
# => "LADEN"
|
72
74
|
```
|
73
75
|
|
74
|
-
The state names are extracted
|
76
|
+
The state names are extracted from the JavaScript source code returned by the SENEC web interface.
|
75
77
|
|
76
78
|
## Development
|
77
79
|
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday/net_http_persistent'
|
3
|
+
require 'faraday-request-timer'
|
4
|
+
require 'forwardable'
|
5
|
+
|
6
|
+
module Senec
|
7
|
+
class Connection
|
8
|
+
def initialize(host:, schema: 'http')
|
9
|
+
@url = "#{schema}://#{host}"
|
10
|
+
end
|
11
|
+
|
12
|
+
extend Forwardable
|
13
|
+
def_delegators :faraday, :get, :post
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def faraday
|
18
|
+
@faraday ||= Faraday.new @url,
|
19
|
+
ssl: { verify: false },
|
20
|
+
headers: {
|
21
|
+
'Connection' => 'keep-alive'
|
22
|
+
} do |f|
|
23
|
+
f.request :timer
|
24
|
+
f.adapter :net_http_persistent, pool_size: 5 do |http|
|
25
|
+
http.idle_timeout = 30
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/senec/request.rb
CHANGED
@@ -1,16 +1,14 @@
|
|
1
|
-
require 'httparty'
|
2
1
|
require 'senec/value'
|
3
2
|
require 'senec/constants'
|
4
3
|
|
5
4
|
module Senec
|
6
5
|
class Request
|
7
|
-
def initialize(
|
8
|
-
@
|
9
|
-
@schema = schema
|
6
|
+
def initialize(connection:, state_names: nil)
|
7
|
+
@connection = connection
|
10
8
|
@state_names = state_names
|
11
9
|
end
|
12
10
|
|
13
|
-
attr_reader :
|
11
|
+
attr_reader :connection, :state_names
|
14
12
|
|
15
13
|
def house_power
|
16
14
|
get('ENERGY', 'GUI_HOUSE_POW')
|
@@ -73,10 +71,16 @@ module Senec
|
|
73
71
|
web_time - (utc_offset * 60)
|
74
72
|
end
|
75
73
|
|
74
|
+
def response_duration
|
75
|
+
raw_response.env[:duration]
|
76
|
+
end
|
77
|
+
|
76
78
|
private
|
77
79
|
|
78
80
|
def get(*keys)
|
79
|
-
|
81
|
+
return unless parsed_response
|
82
|
+
|
83
|
+
value = parsed_response.dig(*keys)
|
80
84
|
|
81
85
|
if value.is_a?(Array)
|
82
86
|
value.map do |v|
|
@@ -91,24 +95,32 @@ module Senec
|
|
91
95
|
raise Senec::Error, "Decoding failed for #{keys.join('.')}: #{e.message}"
|
92
96
|
end
|
93
97
|
|
94
|
-
def
|
95
|
-
@
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
verify: false
|
103
|
-
)
|
104
|
-
raise Senec::Error, res.message.to_s unless res.success?
|
98
|
+
def parsed_response
|
99
|
+
@parsed_response ||= JSON.parse(raw_response.body)
|
100
|
+
end
|
101
|
+
|
102
|
+
def raw_response
|
103
|
+
@raw_response ||= begin
|
104
|
+
response = connection.post(url, request_body, request_header)
|
105
|
+
raise Senec::Error, response.status unless response.success?
|
105
106
|
|
106
|
-
|
107
|
+
response
|
107
108
|
end
|
108
109
|
end
|
109
110
|
|
110
111
|
def url
|
111
|
-
|
112
|
+
'/lala.cgi'
|
113
|
+
end
|
114
|
+
|
115
|
+
def request_body
|
116
|
+
JSON.generate(Senec::BASIC_REQUEST)
|
117
|
+
end
|
118
|
+
|
119
|
+
def request_header
|
120
|
+
{
|
121
|
+
'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8',
|
122
|
+
'Accept' => 'application/json, text/javascript, */*; q=0.01'
|
123
|
+
}
|
112
124
|
end
|
113
125
|
end
|
114
126
|
end
|
data/lib/senec/state.rb
CHANGED
@@ -1,13 +1,10 @@
|
|
1
|
-
require 'httparty'
|
2
|
-
|
3
1
|
module Senec
|
4
2
|
class State
|
5
|
-
def initialize(
|
6
|
-
@
|
7
|
-
@schema = schema
|
3
|
+
def initialize(connection:)
|
4
|
+
@connection = connection
|
8
5
|
end
|
9
6
|
|
10
|
-
attr_reader :
|
7
|
+
attr_reader :connection
|
11
8
|
|
12
9
|
# Extract state names from JavaScript file, which is formatted like this:
|
13
10
|
#
|
@@ -16,8 +13,8 @@ module Senec
|
|
16
13
|
# 1: "SECOND STATE",
|
17
14
|
# ...
|
18
15
|
# };
|
19
|
-
def names
|
20
|
-
response.match(FILE_REGEX)[0].split("\n").each_with_object({}) do |line, hash|
|
16
|
+
def names(language: :de)
|
17
|
+
response(language:).match(FILE_REGEX)[0].split("\n").each_with_object({}) do |line, hash|
|
21
18
|
key, value = line.match(LINE_REGEX)&.captures
|
22
19
|
next unless key && value
|
23
20
|
|
@@ -30,18 +27,25 @@ module Senec
|
|
30
27
|
FILE_REGEX = /var system_state_name = \{(.*?)\};/m
|
31
28
|
LINE_REGEX = /(\d+)\s*:\s*"(.*)"/
|
32
29
|
|
33
|
-
def response
|
34
|
-
|
35
|
-
|
36
|
-
raise Senec::Error, res.message unless res.success?
|
30
|
+
def response(language:)
|
31
|
+
res = connection.get url(language:)
|
32
|
+
raise Senec::Error, res.message unless res.success?
|
37
33
|
|
38
|
-
|
39
|
-
end
|
34
|
+
res.body
|
40
35
|
end
|
41
36
|
|
42
|
-
# Use the JavaScript file
|
43
|
-
def url
|
44
|
-
|
37
|
+
# Use the JavaScript file containing English/German/Italian names from the SENEC web interface
|
38
|
+
def url(language:)
|
39
|
+
case language
|
40
|
+
when :en
|
41
|
+
'/js/EN-en.js'
|
42
|
+
when :de
|
43
|
+
'/js/DE-de.js'
|
44
|
+
when :it
|
45
|
+
'/js/IT-it.js'
|
46
|
+
else
|
47
|
+
raise Senec::Error, "Language #{language} not supported"
|
48
|
+
end
|
45
49
|
end
|
46
50
|
end
|
47
51
|
end
|
data/lib/senec/version.rb
CHANGED
data/lib/senec.rb
CHANGED
data/senec.gemspec
CHANGED
@@ -10,8 +10,10 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.description = 'Access your local SENEC Solar Battery Storage System'
|
11
11
|
spec.homepage = 'https://github.com/solectrus/senec'
|
12
12
|
spec.license = 'MIT'
|
13
|
-
spec.required_ruby_version = Gem::Requirement.new('>= 3.
|
14
|
-
spec.add_runtime_dependency '
|
13
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 3.2.0')
|
14
|
+
spec.add_runtime_dependency 'faraday'
|
15
|
+
spec.add_runtime_dependency 'faraday-net_http_persistent'
|
16
|
+
spec.add_runtime_dependency 'faraday-request-timer'
|
15
17
|
|
16
18
|
spec.metadata['homepage_uri'] = spec.homepage
|
17
19
|
spec.metadata['source_code_uri'] = 'https://github.com/solectrus/senec'
|
metadata
CHANGED
@@ -1,17 +1,45 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: senec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Georg Ledermann
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-08
|
11
|
+
date: 2023-09-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faraday-net_http_persistent
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: faraday-request-timer
|
15
43
|
requirement: !ruby/object:Gem::Requirement
|
16
44
|
requirements:
|
17
45
|
- - ">="
|
@@ -44,6 +72,7 @@ files:
|
|
44
72
|
- bin/console
|
45
73
|
- bin/setup
|
46
74
|
- lib/senec.rb
|
75
|
+
- lib/senec/connection.rb
|
47
76
|
- lib/senec/constants.rb
|
48
77
|
- lib/senec/request.rb
|
49
78
|
- lib/senec/state.rb
|
@@ -66,7 +95,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
66
95
|
requirements:
|
67
96
|
- - ">="
|
68
97
|
- !ruby/object:Gem::Version
|
69
|
-
version: 3.
|
98
|
+
version: 3.2.0
|
70
99
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
100
|
requirements:
|
72
101
|
- - ">="
|