atrea_control 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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