atrea_control 1.1.0 → 1.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 857675ccedb6095d28dced21a663615a053d1d12704da407ea0e6c029bd657eb
4
- data.tar.gz: e2ed731b15bd2d742e230da0ae1b0b276f3b3d8a47dacac9f920424891507ed8
3
+ metadata.gz: ff5e62d3cbb95e39a1b342fa6662636255b8d78b6d76ab54f1e4c3cc12841afc
4
+ data.tar.gz: b1aa30c99ff332e261cb3c9e9752bba0eedd16e730bec244c67e91b51b2ab661
5
5
  SHA512:
6
- metadata.gz: 98f9cbff3552cfc90bf823048d5724b56b0f40877a096bab44181c4890c310bda7c6bb2238376529c730070746455f36a5efe10fd0bf6d75ac62108c280052b9
7
- data.tar.gz: 7b5737cdd13aae0767a6ed41329ddbb886c6002e2d2bb65b248a35306a582859056d32afd7253fab54ae026a22f487ce700ce095ceb4e0dcaf416d459961759b
6
+ metadata.gz: 881da41972aea45c4e3ea36b2a14ec44d87c9a8d42e6249048780bcfb9066c8c42b35d27770be7f23663a13cc3f0b663b621030adb58f52714851d7d3a833354
7
+ data.tar.gz: ee2aaa4913ab06f77ff3fab98661b53085519dffdb1b49786d39e32db80d365618d274e3aef17d12e6041bba9d8d7f030afe5616e5c106c16ccd84062bb88b83
data/.rubocop_todo.yml CHANGED
@@ -1,12 +1,12 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config --auto-gen-only-exclude`
3
- # on 2021-09-13 19:43:25 UTC using RuboCop version 1.20.0.
3
+ # on 2021-10-26 20:31:23 UTC using RuboCop version 1.22.2.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 1
9
+ # Offense count: 2
10
10
  # Configuration parameters: CountComments, Max, CountAsOne, ExcludedMethods, IgnoredMethods.
11
11
  # IgnoredMethods: refine
12
12
  Metrics/BlockLength:
@@ -14,13 +14,19 @@ Metrics/BlockLength:
14
14
  - '**/*.gemspec'
15
15
  - 'spec/atrea_control/duplex_spec.rb'
16
16
 
17
- # Offense count: 4
17
+ # Offense count: 1
18
+ # Configuration parameters: CountComments, Max, CountAsOne.
19
+ Metrics/ClassLength:
20
+ Exclude:
21
+ - 'lib/atrea_control/duplex.rb'
22
+
23
+ # Offense count: 5
18
24
  # Configuration parameters: .
19
25
  # SupportedStyles: have_received, receive
20
26
  RSpec/MessageSpies:
21
27
  EnforcedStyle: receive
22
28
 
23
- # Offense count: 1
29
+ # Offense count: 2
24
30
  # Configuration parameters: Max.
25
31
  RSpec/MultipleExpectations:
26
32
  Exclude:
@@ -31,7 +37,7 @@ RSpec/StubbedMock:
31
37
  Exclude:
32
38
  - 'spec/atrea_control/duplex_spec.rb'
33
39
 
34
- # Offense count: 4
40
+ # Offense count: 5
35
41
  RSpec/SubjectStub:
36
42
  Exclude:
37
43
  - 'spec/atrea_control/duplex_spec.rb'
@@ -60,9 +66,9 @@ Style/MutableConstant:
60
66
  Exclude:
61
67
  - 'spec/atrea_control/duplex_spec.rb'
62
68
 
63
- # Offense count: 1
69
+ # Offense count: 2
64
70
  # Cop supports --auto-correct.
65
- # Configuration parameters: AutoCorrect, Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
71
+ # Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
66
72
  # URISchemes: http, https
67
73
  Layout/LineLength:
68
74
  Exclude:
data/CHANGELOG.md CHANGED
@@ -1,4 +1,8 @@
1
1
  ## [Unreleased]
2
+ ## [1.2.0] - 2021-10-26
3
+ ### Changed
4
+ - use internal unit.php for read values
5
+ - reload login automatically if session expire
2
6
  ## [1.1.0] - 2021-10-22
3
7
  ### Added
4
8
  - to_json
data/Gemfile CHANGED
@@ -9,4 +9,7 @@ gem "rake", "~> 13.0"
9
9
  gem "rspec", "~> 3.10"
10
10
  gem "rubocop", "~> 1.7", require: false
11
11
  gem "rubocop-rspec", "~> 2.4", require: false
12
- gem "simplecov", require: false, group: :test
12
+ group :test do
13
+ gem "simplecov", require: false
14
+ gem "webmock", "~> 3.14"
15
+ end
data/Gemfile.lock CHANGED
@@ -1,22 +1,49 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- atrea_control (1.1.0)
4
+ atrea_control (1.2.0)
5
+ nokogiri (~> 1.12)
6
+ rest-client (~> 2.1)
5
7
  selenium-webdriver (~> 3.142)
6
8
 
7
9
  GEM
8
10
  remote: https://rubygems.org/
9
11
  specs:
12
+ addressable (2.8.0)
13
+ public_suffix (>= 2.0.2, < 5.0)
10
14
  ast (2.4.2)
11
15
  childprocess (3.0.0)
16
+ crack (0.4.5)
17
+ rexml
12
18
  diff-lcs (1.4.4)
13
19
  docile (1.4.0)
14
- parallel (1.20.1)
20
+ domain_name (0.5.20190701)
21
+ unf (>= 0.0.5, < 1.0.0)
22
+ hashdiff (1.0.1)
23
+ http-accept (1.7.0)
24
+ http-cookie (1.0.4)
25
+ domain_name (~> 0.5)
26
+ mime-types (3.3.1)
27
+ mime-types-data (~> 3.2015)
28
+ mime-types-data (3.2021.0901)
29
+ netrc (0.11.0)
30
+ nokogiri (1.12.5-x86_64-darwin)
31
+ racc (~> 1.4)
32
+ nokogiri (1.12.5-x86_64-linux)
33
+ racc (~> 1.4)
34
+ parallel (1.21.0)
15
35
  parser (3.0.2.0)
16
36
  ast (~> 2.4.1)
37
+ public_suffix (4.0.6)
38
+ racc (1.6.0)
17
39
  rainbow (3.0.0)
18
40
  rake (13.0.6)
19
41
  regexp_parser (2.1.1)
42
+ rest-client (2.1.0)
43
+ http-accept (>= 1.7.0, < 2.0)
44
+ http-cookie (>= 1.0.2, < 2.0)
45
+ mime-types (>= 1.16, < 4.0)
46
+ netrc (~> 0.8)
20
47
  rexml (3.2.5)
21
48
  rspec (3.10.0)
22
49
  rspec-core (~> 3.10.0)
@@ -31,20 +58,19 @@ GEM
31
58
  diff-lcs (>= 1.2.0, < 2.0)
32
59
  rspec-support (~> 3.10.0)
33
60
  rspec-support (3.10.2)
34
- rubocop (1.20.0)
61
+ rubocop (1.22.2)
35
62
  parallel (~> 1.10)
36
63
  parser (>= 3.0.0.0)
37
64
  rainbow (>= 2.2.2, < 4.0)
38
65
  regexp_parser (>= 1.8, < 3.0)
39
66
  rexml
40
- rubocop-ast (>= 1.9.1, < 2.0)
67
+ rubocop-ast (>= 1.12.0, < 2.0)
41
68
  ruby-progressbar (~> 1.7)
42
69
  unicode-display_width (>= 1.4.0, < 3.0)
43
- rubocop-ast (1.11.0)
70
+ rubocop-ast (1.12.0)
44
71
  parser (>= 3.0.1.1)
45
- rubocop-rspec (2.4.0)
46
- rubocop (~> 1.0)
47
- rubocop-ast (>= 1.1.0)
72
+ rubocop-rspec (2.5.0)
73
+ rubocop (~> 1.19)
48
74
  ruby-progressbar (1.11.0)
49
75
  rubyzip (2.3.2)
50
76
  selenium-webdriver (3.142.7)
@@ -56,7 +82,14 @@ GEM
56
82
  simplecov_json_formatter (~> 0.1)
57
83
  simplecov-html (0.12.3)
58
84
  simplecov_json_formatter (0.1.3)
59
- unicode-display_width (2.0.0)
85
+ unf (0.1.4)
86
+ unf_ext
87
+ unf_ext (0.0.8)
88
+ unicode-display_width (2.1.0)
89
+ webmock (3.14.0)
90
+ addressable (>= 2.8.0)
91
+ crack (>= 0.3.2)
92
+ hashdiff (>= 0.4.0, < 2.0.0)
60
93
 
61
94
  PLATFORMS
62
95
  x86_64-darwin-19
@@ -69,6 +102,7 @@ DEPENDENCIES
69
102
  rubocop (~> 1.7)
70
103
  rubocop-rspec (~> 2.4)
71
104
  simplecov
105
+ webmock (~> 3.14)
72
106
 
73
107
  BUNDLED WITH
74
108
  2.2.17
@@ -34,5 +34,7 @@ Gem::Specification.new do |spec|
34
34
  # For more information and examples about making a new gem, checkout our
35
35
  # guide at: https://bundler.io/guides/creating_gem.html
36
36
 
37
+ spec.add_dependency "nokogiri", "~> 1.12"
38
+ spec.add_dependency "rest-client", "~> 2.1"
37
39
  spec.add_dependency "selenium-webdriver", "~> 3.142"
38
40
  end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "logger"
4
+ require "nokogiri"
5
+ require "rest-client"
4
6
  require "selenium-webdriver"
5
7
 
6
8
  module AtreaControl
@@ -8,6 +10,10 @@ module AtreaControl
8
10
  class Duplex
9
11
  CONTROL_URI = "https://control.atrea.eu/"
10
12
 
13
+ attr_reader :current_mode, :current_power, :outdoor_temperature
14
+ # @return [DateTime] store time of last update
15
+ attr_reader :valid_for
16
+
11
17
  # @param [String] login
12
18
  # @param [String] password
13
19
  # @param [Hash] sensors_map which box is related to sensor ID
@@ -21,6 +27,7 @@ module AtreaControl
21
27
  @sensors = sensors_map
22
28
  end
23
29
 
30
+ # @return [Selenium::WebDriver::Firefox::Driver]
24
31
  def driver
25
32
  return @driver if defined?(@driver)
26
33
 
@@ -44,8 +51,7 @@ module AtreaControl
44
51
 
45
52
  submit = form.find_element(css: "input[type=submit]")
46
53
  submit.click
47
- finish_login
48
- inspect
54
+ finish_login && inspect
49
55
  end
50
56
 
51
57
  # Retrieve dashboard URI from object tag and open it again
@@ -64,82 +70,124 @@ module AtreaControl
64
70
  container.text
65
71
  end
66
72
 
67
- def unit_id
68
- return unless logged?
69
-
70
- element = driver.find_element css: "div#pageTitle > a"
71
- element.attribute(:href) =~ /unit=(\d+)/
72
- Regexp.last_match(1)
73
+ # @return [String] ID of logged user
74
+ def user_id
75
+ @user_id ||= driver.execute_script("return window._user")
73
76
  end
74
77
 
75
- # @return [Float]
76
- def outdoor_temperature
77
- return unless logged?
78
-
79
- element = sensor_element(@sensors[__method__])
80
- element.find_element(css: "div").text.to_f
78
+ # @return [String] ID of recuperation unit
79
+ def unit_id
80
+ @unit_id ||= driver.execute_script("return window._unit")
81
81
  end
82
82
 
83
- # @return [Float] in %
84
- def current_power
85
- return unless logged?
86
-
87
- # element = driver.find_element id: "contentBox#{@sensors[__method__]}"
88
- element = sensor_element(@sensors[__method__])
89
- element.find_element(css: "div:first-child").text.to_f
83
+ # @return [String]
84
+ def user_auth
85
+ @user_auth ||= driver.execute_script("return window.user")&.[] "auth"
90
86
  end
91
87
 
92
88
  # @return [String]
93
- def current_mode
94
- return unless logged?
89
+ def current_mode_name
90
+ return current_mode unless logged?
95
91
 
96
- element = sensor_element(@sensors[__method__])
92
+ element = sensor_element(@sensors[:current_mode])
97
93
  element.find_element(css: "div:first-child").text
98
94
  end
99
95
 
100
96
  # quit selenium browser
101
97
  def close
102
98
  @logged = false
99
+ @user_auth = nil
103
100
  driver.quit
101
+ remove_instance_variable :@driver
104
102
  end
105
103
 
104
+ alias logout! close
105
+
106
106
  def as_json(_options = nil)
107
107
  {
108
108
  logged: logged?,
109
- current_mode: current_mode,
109
+ current_mode: current_mode_name,
110
110
  current_power: current_power,
111
111
  outdoor_temperature: outdoor_temperature,
112
+ valid_for: valid_for,
112
113
  }
113
114
  end
114
115
 
116
+ alias values as_json
117
+
115
118
  def to_json(*args)
116
119
  as_json.to_json(*args)
117
120
  end
118
121
 
119
122
  def inspect
120
- "<AtreaControl name: '#{name}' outdoor_temperature: #{outdoor_temperature}°C current_power: #{current_power}% current_mode: '#{current_mode}'>"
123
+ "<AtreaControl name: '#{name}' outdoor_temperature: '#{outdoor_temperature}°C' current_power: '#{current_power}%' current_mode: '#{current_mode_name}' valid_for: '#{valid_for}'>"
121
124
  end
122
125
 
126
+ def call_unit!
127
+ return false unless user_auth
128
+
129
+ parse_response(response_comm_unit)
130
+ @valid_for = Time.now
131
+ as_json
132
+ rescue RestClient::Forbidden
133
+ close if @logged
134
+ login && call_unit!
135
+ end
123
136
 
124
137
  private
125
138
 
126
- def logger
127
- @logger ||= ::Logger.new($stdout)
139
+ def parse_response(response)
140
+ xml = Nokogiri::XML response.body
141
+ sensors_values = @sensors.transform_values do |id|
142
+ xml.xpath("//O[@I=\"#{id}\"]/@V").last&.value
143
+ end
144
+ refresh_data(sensors_values)
128
145
  end
129
146
 
130
- def sensor_element(sensor_id)
131
- driver.find_element id: "contentBox#{sensor_id}"
147
+ # @param [Hash] values
148
+ # @return [Hash]
149
+ def refresh_data(values)
150
+ @outdoor_temperature = values[:outdoor_temperature].to_f / 10
151
+ @current_power = values[:current_power].to_f
152
+ @current_mode = mode_map[values[:current_mode]]
153
+
154
+ as_json
155
+ end
156
+
157
+ # ? I10204 ?
158
+ def mode_map
159
+ { "0" => "Vypnuto", "1" => "Automat", "2" => "Větrání", "6" => "Rozvážení" }
160
+ end
161
+
162
+ def logger
163
+ @logger ||= ::Logger.new($stdout)
132
164
  end
133
165
 
134
166
  def finish_login
135
167
  13.times do |i|
136
168
  return true if open_dashboard
137
169
  rescue Selenium::WebDriver::Error::NoSuchElementError => _e
138
- t = [5 * (1 + i), 25].min
170
+ t = [3 * (1 + i), 25].min
139
171
  logger.debug "waiting #{t}s for login..."
140
172
  sleep t
141
173
  end
142
174
  raise Error, "unable to login"
143
175
  end
176
+
177
+ def sensor_element(sensor_id)
178
+ driver.find_element id: "contentBox#{sensor_id}"
179
+ end
180
+
181
+ # @return [RestClient::Response]
182
+ def response_comm_unit
183
+ params = {
184
+ _user: user_id,
185
+ _unit: unit_id,
186
+ auth: user_auth,
187
+ _t: "config/xml.xml",
188
+ }
189
+ autologin_token = CGI.escape([@login, @password].join("\b"))
190
+ RestClient.get "https://control.atrea.eu/comm/sw/unit.php", { Cookie: "autoLogin=#{autologin_token}", params: params }
191
+ end
144
192
  end
145
193
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AtreaControl
4
- VERSION = "1.1.0"
4
+ VERSION = "1.2.0"
5
5
  end
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: atrea_control
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lukáš Pokorný
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-10-22 00:00:00.000000000 Z
11
+ date: 2021-10-27 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.12'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rest-client
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.1'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: selenium-webdriver
15
43
  requirement: !ruby/object:Gem::Requirement