senec 0.18.0 → 0.19.0
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 +4 -4
- data/.DS_Store +0 -0
- data/.env +6 -0
- data/.env.test +1 -1
- data/.gitignore +13 -0
- data/.rspec_status +69 -0
- data/.rubocop.yml +1 -1
- data/.ruby-lsp/.gitignore +1 -0
- data/.ruby-lsp/Gemfile +6 -0
- data/.ruby-lsp/Gemfile.lock +170 -0
- data/.ruby-lsp/main_lockfile_hash +1 -0
- data/.ruby-lsp/needs_update +0 -0
- data/README.md +50 -79
- data/coverage/.last_run.json +5 -0
- data/coverage/.resultset.json +1367 -0
- data/coverage/.resultset.json.lock +0 -0
- data/coverage/assets/0.13.2/DataTables-1.10.20/images/sort_asc.png +0 -0
- data/coverage/assets/0.13.2/DataTables-1.10.20/images/sort_asc_disabled.png +0 -0
- data/coverage/assets/0.13.2/DataTables-1.10.20/images/sort_both.png +0 -0
- data/coverage/assets/0.13.2/DataTables-1.10.20/images/sort_desc.png +0 -0
- data/coverage/assets/0.13.2/DataTables-1.10.20/images/sort_desc_disabled.png +0 -0
- data/coverage/assets/0.13.2/application.css +1 -0
- data/coverage/assets/0.13.2/application.js +7 -0
- data/coverage/assets/0.13.2/colorbox/border.png +0 -0
- data/coverage/assets/0.13.2/colorbox/controls.png +0 -0
- data/coverage/assets/0.13.2/colorbox/loading.gif +0 -0
- data/coverage/assets/0.13.2/colorbox/loading_background.png +0 -0
- data/coverage/assets/0.13.2/favicon_green.png +0 -0
- data/coverage/assets/0.13.2/favicon_red.png +0 -0
- data/coverage/assets/0.13.2/favicon_yellow.png +0 -0
- data/coverage/assets/0.13.2/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/coverage/assets/0.13.2/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/coverage/assets/0.13.2/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/coverage/assets/0.13.2/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/coverage/assets/0.13.2/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/coverage/assets/0.13.2/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/coverage/assets/0.13.2/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/coverage/assets/0.13.2/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/coverage/assets/0.13.2/images/ui-icons_222222_256x240.png +0 -0
- data/coverage/assets/0.13.2/images/ui-icons_2e83ff_256x240.png +0 -0
- data/coverage/assets/0.13.2/images/ui-icons_454545_256x240.png +0 -0
- data/coverage/assets/0.13.2/images/ui-icons_888888_256x240.png +0 -0
- data/coverage/assets/0.13.2/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/coverage/assets/0.13.2/loading.gif +0 -0
- data/coverage/assets/0.13.2/magnify.png +0 -0
- data/coverage/coverage.json +1368 -0
- data/coverage/index.html +15044 -0
- data/lib/.DS_Store +0 -0
- data/lib/senec/cloud/connection.rb +96 -39
- data/lib/senec/cloud/error.rb +0 -6
- data/lib/senec/cloud/stats_overview.rb +52 -0
- data/lib/senec/cloud/wallboxes.rb +52 -0
- data/lib/senec/local/request.rb +1 -1
- data/lib/senec/local/state.rb +1 -0
- data/lib/senec/version.rb +1 -1
- data/lib/senec.rb +2 -2
- data/pkg/senec-0.1.0.gem +0 -0
- data/pkg/senec-0.10.0.gem +0 -0
- data/pkg/senec-0.11.0.gem +0 -0
- data/pkg/senec-0.12.0.gem +0 -0
- data/pkg/senec-0.13.0.gem +0 -0
- data/pkg/senec-0.14.0.gem +0 -0
- data/pkg/senec-0.15.0.gem +0 -0
- data/pkg/senec-0.17.0.gem +0 -0
- data/pkg/senec-0.17.1.gem +0 -0
- data/pkg/senec-0.17.2.gem +0 -0
- data/pkg/senec-0.18.0.gem +0 -0
- data/pkg/senec-0.2.0.gem +0 -0
- data/pkg/senec-0.3.0.gem +0 -0
- data/pkg/senec-0.4.0.gem +0 -0
- data/pkg/senec-0.5.0.gem +0 -0
- data/pkg/senec-0.6.0.gem +0 -0
- data/pkg/senec-0.6.1.gem +0 -0
- data/pkg/senec-0.6.2.gem +0 -0
- data/pkg/senec-0.7.0.gem +0 -0
- data/pkg/senec-0.7.1.gem +0 -0
- data/pkg/senec-0.7.2.gem +0 -0
- data/pkg/senec-0.8.0.gem +0 -0
- data/pkg/senec-0.9.0.gem +0 -0
- metadata +72 -5
- data/lib/senec/cloud/dashboard.rb +0 -80
- data/lib/senec/cloud/technical_data.rb +0 -69
data/lib/.DS_Store
ADDED
Binary file
|
@@ -1,72 +1,129 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'json'
|
3
|
+
|
1
4
|
module Senec
|
2
5
|
module Cloud
|
6
|
+
BASE_URL = 'https://mein-senec.de'.freeze
|
7
|
+
|
3
8
|
class Connection
|
4
|
-
|
9
|
+
DEFAULT_USER_AGENT = "ruby-senec/#{Senec::VERSION} (+https://github.com/solectrus/senec)".freeze
|
10
|
+
MAX_REDIRECTS = 10
|
11
|
+
|
12
|
+
def initialize(username:, password:, user_agent: DEFAULT_USER_AGENT)
|
5
13
|
@username = username
|
6
14
|
@password = password
|
7
|
-
@
|
15
|
+
@user_agent = user_agent
|
16
|
+
@cookies = {}
|
8
17
|
end
|
9
18
|
|
10
|
-
attr_reader :username, :password
|
19
|
+
attr_reader :username, :password, :user_agent, :cookies
|
11
20
|
|
12
21
|
def authenticated?
|
13
|
-
|
14
|
-
end
|
22
|
+
authenticate if cookies.empty?
|
15
23
|
|
16
|
-
|
17
|
-
get('/v1/senec/systems')
|
24
|
+
cookies.key?('sso.senec.com_KEYCLOAK_IDENTITY')
|
18
25
|
end
|
19
26
|
|
20
|
-
def
|
21
|
-
|
27
|
+
def authenticate
|
28
|
+
response = request_with_redirects(Cloud::BASE_URL)
|
29
|
+
|
30
|
+
# Find form with username and password inputs
|
31
|
+
form_match = find_login_form(response.body)
|
32
|
+
raise Error, 'Login form not found!' unless form_match
|
22
33
|
|
23
|
-
|
34
|
+
# Perform the login request with the extracted form action URL
|
35
|
+
form_action = form_match.gsub('&', '&')
|
36
|
+
request_with_redirects(
|
37
|
+
form_action, {
|
38
|
+
'username' => username,
|
39
|
+
'password' => password
|
40
|
+
},
|
41
|
+
)
|
24
42
|
end
|
25
43
|
|
26
|
-
def
|
27
|
-
|
28
|
-
connection.get(path, params, { authorization: token })
|
29
|
-
end
|
44
|
+
def simple_request(url)
|
45
|
+
perform_request(url)
|
30
46
|
end
|
31
47
|
|
32
|
-
def
|
33
|
-
|
34
|
-
|
48
|
+
def request_with_redirects(url, data = nil)
|
49
|
+
uri = URI(url)
|
50
|
+
redirect_count = 0
|
51
|
+
response = nil
|
52
|
+
|
53
|
+
loop do
|
54
|
+
response = perform_request(uri.to_s, data)
|
55
|
+
store_cookies(response)
|
56
|
+
|
57
|
+
break unless (300..399).cover?(response.status)
|
58
|
+
|
59
|
+
location = response.headers['location']
|
60
|
+
break unless location
|
61
|
+
|
62
|
+
redirect_count += 1
|
63
|
+
raise 'Too many redirects!' if redirect_count > MAX_REDIRECTS
|
64
|
+
|
65
|
+
uri = location.start_with?('http') ? URI(location) : URI.join(uri, location)
|
66
|
+
data = nil # Clear data after first request (no POST redirects)
|
35
67
|
end
|
36
|
-
end
|
37
68
|
|
38
|
-
|
39
|
-
@token ||= login['token']
|
69
|
+
response
|
40
70
|
end
|
41
71
|
|
42
72
|
private
|
43
73
|
|
44
|
-
def
|
45
|
-
|
74
|
+
def find_login_form(html_body)
|
75
|
+
# Find all forms and check if they contain both username and password inputs
|
76
|
+
html_body.scan(%r{<form[^>]*action="([^"]+)"[^>]*>(.*?)</form>}m).each do |action, form_content|
|
77
|
+
has_username = form_content.match(/input[^>]*name=["']username["'][^>]*/)
|
78
|
+
has_password = form_content.match(/input[^>]*name=["']password["'][^>]*/)
|
79
|
+
|
80
|
+
return action if has_username && has_password
|
81
|
+
end
|
82
|
+
|
83
|
+
# :nocov:
|
84
|
+
nil
|
85
|
+
# :nocov:
|
46
86
|
end
|
47
87
|
|
48
|
-
def
|
49
|
-
@
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
f.adapter :net_http_persistent, pool_size: 5 do |http|
|
55
|
-
# :nocov:
|
56
|
-
http.idle_timeout = 120
|
57
|
-
# :nocov:
|
58
|
-
end
|
88
|
+
def faraday
|
89
|
+
@faraday ||= Faraday.new do |f|
|
90
|
+
f.adapter :net_http_persistent, pool_size: 1 do |http|
|
91
|
+
# :nocov:
|
92
|
+
http.idle_timeout = 400
|
93
|
+
# :nocov:
|
59
94
|
end
|
95
|
+
end
|
60
96
|
end
|
61
97
|
|
62
|
-
def
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
98
|
+
def perform_request(url, data = nil)
|
99
|
+
method = data ? :post : :get
|
100
|
+
faraday.public_send(method, url) do |req|
|
101
|
+
configure_request_headers(req)
|
102
|
+
if method == :post
|
103
|
+
req.body = URI.encode_www_form(data)
|
104
|
+
req.headers['content-type'] = 'application/x-www-form-urlencoded'
|
105
|
+
end
|
67
106
|
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def configure_request_headers(request)
|
110
|
+
request.headers['user-agent'] = user_agent
|
111
|
+
request.headers['connection'] = 'keep-alive'
|
112
|
+
request.headers['cookie'] = cookies.values.join('; ') unless cookies.empty?
|
113
|
+
end
|
68
114
|
|
69
|
-
|
115
|
+
def store_cookies(response)
|
116
|
+
host = URI(response.env.url).host
|
117
|
+
cookie_header = response.headers['set-cookie']
|
118
|
+
return unless cookie_header
|
119
|
+
|
120
|
+
Array(cookie_header).each do |cookie_string|
|
121
|
+
cookie_string.split(', ').each do |cookie|
|
122
|
+
cookie_name = cookie.split('=').first
|
123
|
+
cookie_value = cookie.split(';').first
|
124
|
+
@cookies["#{host}_#{cookie_name}"] = cookie_value
|
125
|
+
end
|
126
|
+
end
|
70
127
|
end
|
71
128
|
end
|
72
129
|
end
|
data/lib/senec/cloud/error.rb
CHANGED
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative 'connection'
|
2
|
+
require 'net/http'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
# Model for the Senec statistics overview data.
|
6
|
+
#
|
7
|
+
# Example use:
|
8
|
+
#
|
9
|
+
# connection = Senec::Cloud::Connection.new(username: '...', password: '...')
|
10
|
+
#
|
11
|
+
# # Get the data of a specific system:
|
12
|
+
# Senec::Cloud::StatsOverview.new(connection:, system_id: 1).data
|
13
|
+
#
|
14
|
+
# # Get the data of the default system (system_id 0):
|
15
|
+
# Senec::Cloud::StatsOverview.new(connection:).data
|
16
|
+
#
|
17
|
+
module Senec
|
18
|
+
module Cloud
|
19
|
+
class StatsOverview
|
20
|
+
PATH = '/endkunde/api/status/getstatusoverview.php'.freeze
|
21
|
+
|
22
|
+
def initialize(connection: nil, system_id: 0)
|
23
|
+
raise ArgumentError unless connection
|
24
|
+
|
25
|
+
@connection = connection
|
26
|
+
@system_id = system_id
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_reader :connection, :system_id
|
30
|
+
|
31
|
+
def data
|
32
|
+
@data ||= fetch_data
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def fetch_data
|
38
|
+
connection.authenticate unless connection.authenticated?
|
39
|
+
|
40
|
+
uri = URI("#{Cloud::BASE_URL}#{PATH}")
|
41
|
+
uri.query = URI.encode_www_form(anlageNummer: system_id)
|
42
|
+
|
43
|
+
response = connection.simple_request(uri.to_s)
|
44
|
+
JSON.parse(response.body)
|
45
|
+
rescue JSON::ParserError
|
46
|
+
# :nocov:
|
47
|
+
raise Error, "Failed to parse response from #{PATH}"
|
48
|
+
# :nocov:
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative 'connection'
|
2
|
+
require 'net/http'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
# Model for the Senec wallboxes data.
|
6
|
+
#
|
7
|
+
# Example use:
|
8
|
+
#
|
9
|
+
# connection = Senec::Cloud::Connection.new(username: '...', password: '...')
|
10
|
+
#
|
11
|
+
# # Get the data of a specific system:
|
12
|
+
# Senec::Cloud::Wallboxes.new(connection:, system_id: 1).data
|
13
|
+
#
|
14
|
+
# # Get the data of the default system (system_id 0):
|
15
|
+
# Senec::Cloud::Wallboxes.new(connection:).data
|
16
|
+
#
|
17
|
+
module Senec
|
18
|
+
module Cloud
|
19
|
+
class Wallboxes
|
20
|
+
PATH = '/endkunde/api/wallboxes'.freeze
|
21
|
+
|
22
|
+
def initialize(connection: nil, system_id: 0)
|
23
|
+
raise ArgumentError unless connection
|
24
|
+
|
25
|
+
@connection = connection
|
26
|
+
@system_id = system_id
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_reader :connection, :system_id
|
30
|
+
|
31
|
+
def data
|
32
|
+
@data ||= fetch_data
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def fetch_data
|
38
|
+
connection.authenticate unless connection.authenticated?
|
39
|
+
|
40
|
+
uri = URI("#{Cloud::BASE_URL}#{PATH}")
|
41
|
+
uri.query = URI.encode_www_form(anlageNummer: system_id)
|
42
|
+
|
43
|
+
response = connection.simple_request(uri.to_s)
|
44
|
+
JSON.parse(response.body)
|
45
|
+
rescue JSON::ParserError
|
46
|
+
# :nocov:
|
47
|
+
raise Error, "Failed to parse response from #{PATH}"
|
48
|
+
# :nocov:
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/senec/local/request.rb
CHANGED
data/lib/senec/local/state.rb
CHANGED
@@ -39,6 +39,7 @@ module Senec
|
|
39
39
|
# Regex pattern to match the system_state_name definition in the JavaScript file
|
40
40
|
# The file may be minimized, so we need to be flexible with whitespace and line breaks
|
41
41
|
FILE_REGEX = /system_state_name\s*=\s*{\s*([^}]*)\s*}/m
|
42
|
+
private_constant :FILE_REGEX
|
42
43
|
|
43
44
|
def response(language:)
|
44
45
|
res = connection.get url(language:)
|
data/lib/senec/version.rb
CHANGED
data/lib/senec.rb
CHANGED
data/pkg/senec-0.1.0.gem
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/pkg/senec-0.2.0.gem
ADDED
Binary file
|
data/pkg/senec-0.3.0.gem
ADDED
Binary file
|
data/pkg/senec-0.4.0.gem
ADDED
Binary file
|
data/pkg/senec-0.5.0.gem
ADDED
Binary file
|
data/pkg/senec-0.6.0.gem
ADDED
Binary file
|
data/pkg/senec-0.6.1.gem
ADDED
Binary file
|
data/pkg/senec-0.6.2.gem
ADDED
Binary file
|
data/pkg/senec-0.7.0.gem
ADDED
Binary file
|
data/pkg/senec-0.7.1.gem
ADDED
Binary file
|
data/pkg/senec-0.7.2.gem
ADDED
Binary file
|
data/pkg/senec-0.8.0.gem
ADDED
Binary file
|
data/pkg/senec-0.9.0.gem
ADDED
Binary file
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: senec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.19.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Georg Ledermann
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: faraday
|
@@ -58,19 +58,63 @@ executables: []
|
|
58
58
|
extensions: []
|
59
59
|
extra_rdoc_files: []
|
60
60
|
files:
|
61
|
+
- ".DS_Store"
|
62
|
+
- ".env"
|
61
63
|
- ".env.test"
|
64
|
+
- ".gitignore"
|
62
65
|
- ".rspec"
|
66
|
+
- ".rspec_status"
|
63
67
|
- ".rubocop.yml"
|
68
|
+
- ".ruby-lsp/.gitignore"
|
69
|
+
- ".ruby-lsp/Gemfile"
|
70
|
+
- ".ruby-lsp/Gemfile.lock"
|
71
|
+
- ".ruby-lsp/main_lockfile_hash"
|
72
|
+
- ".ruby-lsp/needs_update"
|
64
73
|
- ".vscode/settings.json"
|
65
74
|
- CODE_OF_CONDUCT.md
|
66
75
|
- LICENSE
|
67
76
|
- README.md
|
68
77
|
- Rakefile
|
78
|
+
- coverage/.last_run.json
|
79
|
+
- coverage/.resultset.json
|
80
|
+
- coverage/.resultset.json.lock
|
81
|
+
- coverage/assets/0.13.2/DataTables-1.10.20/images/sort_asc.png
|
82
|
+
- coverage/assets/0.13.2/DataTables-1.10.20/images/sort_asc_disabled.png
|
83
|
+
- coverage/assets/0.13.2/DataTables-1.10.20/images/sort_both.png
|
84
|
+
- coverage/assets/0.13.2/DataTables-1.10.20/images/sort_desc.png
|
85
|
+
- coverage/assets/0.13.2/DataTables-1.10.20/images/sort_desc_disabled.png
|
86
|
+
- coverage/assets/0.13.2/application.css
|
87
|
+
- coverage/assets/0.13.2/application.js
|
88
|
+
- coverage/assets/0.13.2/colorbox/border.png
|
89
|
+
- coverage/assets/0.13.2/colorbox/controls.png
|
90
|
+
- coverage/assets/0.13.2/colorbox/loading.gif
|
91
|
+
- coverage/assets/0.13.2/colorbox/loading_background.png
|
92
|
+
- coverage/assets/0.13.2/favicon_green.png
|
93
|
+
- coverage/assets/0.13.2/favicon_red.png
|
94
|
+
- coverage/assets/0.13.2/favicon_yellow.png
|
95
|
+
- coverage/assets/0.13.2/images/ui-bg_flat_0_aaaaaa_40x100.png
|
96
|
+
- coverage/assets/0.13.2/images/ui-bg_flat_75_ffffff_40x100.png
|
97
|
+
- coverage/assets/0.13.2/images/ui-bg_glass_55_fbf9ee_1x400.png
|
98
|
+
- coverage/assets/0.13.2/images/ui-bg_glass_65_ffffff_1x400.png
|
99
|
+
- coverage/assets/0.13.2/images/ui-bg_glass_75_dadada_1x400.png
|
100
|
+
- coverage/assets/0.13.2/images/ui-bg_glass_75_e6e6e6_1x400.png
|
101
|
+
- coverage/assets/0.13.2/images/ui-bg_glass_95_fef1ec_1x400.png
|
102
|
+
- coverage/assets/0.13.2/images/ui-bg_highlight-soft_75_cccccc_1x100.png
|
103
|
+
- coverage/assets/0.13.2/images/ui-icons_222222_256x240.png
|
104
|
+
- coverage/assets/0.13.2/images/ui-icons_2e83ff_256x240.png
|
105
|
+
- coverage/assets/0.13.2/images/ui-icons_454545_256x240.png
|
106
|
+
- coverage/assets/0.13.2/images/ui-icons_888888_256x240.png
|
107
|
+
- coverage/assets/0.13.2/images/ui-icons_cd0a0a_256x240.png
|
108
|
+
- coverage/assets/0.13.2/loading.gif
|
109
|
+
- coverage/assets/0.13.2/magnify.png
|
110
|
+
- coverage/coverage.json
|
111
|
+
- coverage/index.html
|
112
|
+
- lib/.DS_Store
|
69
113
|
- lib/senec.rb
|
70
114
|
- lib/senec/cloud/connection.rb
|
71
|
-
- lib/senec/cloud/dashboard.rb
|
72
115
|
- lib/senec/cloud/error.rb
|
73
|
-
- lib/senec/cloud/
|
116
|
+
- lib/senec/cloud/stats_overview.rb
|
117
|
+
- lib/senec/cloud/wallboxes.rb
|
74
118
|
- lib/senec/local/connection.rb
|
75
119
|
- lib/senec/local/constants.rb
|
76
120
|
- lib/senec/local/error.rb
|
@@ -78,6 +122,29 @@ files:
|
|
78
122
|
- lib/senec/local/state.rb
|
79
123
|
- lib/senec/local/value.rb
|
80
124
|
- lib/senec/version.rb
|
125
|
+
- pkg/senec-0.1.0.gem
|
126
|
+
- pkg/senec-0.10.0.gem
|
127
|
+
- pkg/senec-0.11.0.gem
|
128
|
+
- pkg/senec-0.12.0.gem
|
129
|
+
- pkg/senec-0.13.0.gem
|
130
|
+
- pkg/senec-0.14.0.gem
|
131
|
+
- pkg/senec-0.15.0.gem
|
132
|
+
- pkg/senec-0.17.0.gem
|
133
|
+
- pkg/senec-0.17.1.gem
|
134
|
+
- pkg/senec-0.17.2.gem
|
135
|
+
- pkg/senec-0.18.0.gem
|
136
|
+
- pkg/senec-0.2.0.gem
|
137
|
+
- pkg/senec-0.3.0.gem
|
138
|
+
- pkg/senec-0.4.0.gem
|
139
|
+
- pkg/senec-0.5.0.gem
|
140
|
+
- pkg/senec-0.6.0.gem
|
141
|
+
- pkg/senec-0.6.1.gem
|
142
|
+
- pkg/senec-0.6.2.gem
|
143
|
+
- pkg/senec-0.7.0.gem
|
144
|
+
- pkg/senec-0.7.1.gem
|
145
|
+
- pkg/senec-0.7.2.gem
|
146
|
+
- pkg/senec-0.8.0.gem
|
147
|
+
- pkg/senec-0.9.0.gem
|
81
148
|
homepage: https://github.com/solectrus/senec
|
82
149
|
licenses:
|
83
150
|
- MIT
|
@@ -100,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
167
|
- !ruby/object:Gem::Version
|
101
168
|
version: '0'
|
102
169
|
requirements: []
|
103
|
-
rubygems_version: 3.
|
170
|
+
rubygems_version: 3.7.1
|
104
171
|
specification_version: 4
|
105
172
|
summary: Unofficial Ruby Client for SENEC Home
|
106
173
|
test_files: []
|
@@ -1,80 +0,0 @@
|
|
1
|
-
require_relative 'connection'
|
2
|
-
|
3
|
-
# Model for the Senec dashboard data.
|
4
|
-
#
|
5
|
-
# Example use:
|
6
|
-
#
|
7
|
-
# connection = Senec::Cloud::Connection.new(username: '...', password: '...')
|
8
|
-
#
|
9
|
-
# # Get the data of a specific system:
|
10
|
-
# Dashboard[connection].find('123456').data
|
11
|
-
#
|
12
|
-
# # Get the data of the default system:
|
13
|
-
# Dashboard[connection].first.data
|
14
|
-
#
|
15
|
-
# By default, it returns v1 data. To get v2 data, use:
|
16
|
-
#
|
17
|
-
# Dashboard[connection].find('123456').data(version: 'v2')
|
18
|
-
# or
|
19
|
-
# Dashboard[connection].first.data(version: 'v2')
|
20
|
-
#
|
21
|
-
module Senec
|
22
|
-
module Cloud
|
23
|
-
class Dashboard
|
24
|
-
AVAILABLE_VERSIONS = %w[v1 v2].freeze
|
25
|
-
DEFAULT_VERSION = 'v1'.freeze
|
26
|
-
|
27
|
-
class Finder
|
28
|
-
def initialize(connection)
|
29
|
-
@connection = connection
|
30
|
-
end
|
31
|
-
attr_reader :connection
|
32
|
-
|
33
|
-
def find(system_id)
|
34
|
-
Dashboard.new(connection:, system_id:)
|
35
|
-
end
|
36
|
-
|
37
|
-
def first
|
38
|
-
find(connection.default_system_id)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def self.[](connection)
|
43
|
-
Finder.new(connection)
|
44
|
-
end
|
45
|
-
|
46
|
-
def initialize(connection: nil, system_id: nil, data: nil)
|
47
|
-
raise ArgumentError unless connection.nil? ^ data.nil?
|
48
|
-
|
49
|
-
@connection = connection
|
50
|
-
@system_id = system_id
|
51
|
-
|
52
|
-
# Useful for testing only
|
53
|
-
@data = {
|
54
|
-
'v1' => data,
|
55
|
-
'v2' => data
|
56
|
-
}
|
57
|
-
end
|
58
|
-
|
59
|
-
def data(version: DEFAULT_VERSION)
|
60
|
-
@data ||= {}
|
61
|
-
@data[version] ||= fetch_data(version:)
|
62
|
-
end
|
63
|
-
|
64
|
-
attr_reader :system_id
|
65
|
-
|
66
|
-
private
|
67
|
-
|
68
|
-
def get(path, params: nil)
|
69
|
-
@connection.get(path, params:)
|
70
|
-
end
|
71
|
-
|
72
|
-
def fetch_data(version:)
|
73
|
-
raise ArgumentError unless AVAILABLE_VERSIONS.include?(version)
|
74
|
-
return unless system_id
|
75
|
-
|
76
|
-
get("/#{version}/senec/systems/#{system_id}/dashboard")
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
@@ -1,69 +0,0 @@
|
|
1
|
-
require_relative 'connection'
|
2
|
-
|
3
|
-
# Model for the Senec technical data.
|
4
|
-
#
|
5
|
-
# Example use:
|
6
|
-
#
|
7
|
-
# connection = Senec::Cloud::Connection.new(username: '...', password: '...')
|
8
|
-
#
|
9
|
-
# # Get the data of a specific system:
|
10
|
-
# TechnicalData[connection].find('123456')
|
11
|
-
#
|
12
|
-
# # Get the data of the default system:
|
13
|
-
# TechnicalData[connection].first
|
14
|
-
#
|
15
|
-
module Senec
|
16
|
-
module Cloud
|
17
|
-
class TechnicalData
|
18
|
-
class Finder
|
19
|
-
def initialize(connection)
|
20
|
-
@connection = connection
|
21
|
-
end
|
22
|
-
attr_reader :connection
|
23
|
-
|
24
|
-
def find(system_id)
|
25
|
-
TechnicalData.new(connection:, system_id:).tap(&:load_data)
|
26
|
-
end
|
27
|
-
|
28
|
-
def first
|
29
|
-
find(connection.default_system_id)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.[](connection)
|
34
|
-
Finder.new(connection)
|
35
|
-
end
|
36
|
-
|
37
|
-
def initialize(connection: nil, system_id: nil, data: nil)
|
38
|
-
raise ArgumentError unless connection.nil? ^ data.nil?
|
39
|
-
|
40
|
-
@connection = connection
|
41
|
-
@system_id = system_id
|
42
|
-
|
43
|
-
# Useful for testing only
|
44
|
-
@data = data
|
45
|
-
end
|
46
|
-
|
47
|
-
def load_data
|
48
|
-
raise 'Data already present!' if @data
|
49
|
-
|
50
|
-
@system_id ||= connection.default_system_id
|
51
|
-
@data = fetch_data
|
52
|
-
end
|
53
|
-
|
54
|
-
attr_reader :system_id, :data
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
def get(path, params: nil)
|
59
|
-
@connection.get(path, params:)
|
60
|
-
end
|
61
|
-
|
62
|
-
def fetch_data
|
63
|
-
return unless system_id
|
64
|
-
|
65
|
-
get("/v1/senec/systems/#{system_id}/technical-data")
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|