atrea_control 1.1.0 → 1.3.1

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: 68f9514437807e5b2866e168be26f647b86e5691b790995a6601cbfaed0a8076
4
+ data.tar.gz: 0bbc369ca0fb7ef6e678785be170f7ce17404acd5c8e8f5972a1f7ac58b4e654
5
5
  SHA512:
6
- metadata.gz: 98f9cbff3552cfc90bf823048d5724b56b0f40877a096bab44181c4890c310bda7c6bb2238376529c730070746455f36a5efe10fd0bf6d75ac62108c280052b9
7
- data.tar.gz: 7b5737cdd13aae0767a6ed41329ddbb886c6002e2d2bb65b248a35306a582859056d32afd7253fab54ae026a22f487ce700ce095ceb4e0dcaf416d459961759b
6
+ metadata.gz: 326fbbe14ad1021edbb031928fc2fb99e835fe419dd28acd2e77f73c2547915bc8ff8db8180333960eb5d21508c089edc2e730a455247437f2cc338976f93840
7
+ data.tar.gz: 50c81e105c82a2ae3197d8c21c899c8a6bcc53ad97fbc34bca61d2913b774d82b598aee27a18bf517d44e83a5d8ed3ce4e833d96a2ea575c7e3dceec2fbc157e
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ .DS_Store
1
2
  /.idea
2
3
  /.bundle/
3
4
  /.yardoc
data/.rubocop_todo.yml CHANGED
@@ -1,12 +1,29 @@
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-30 20:32:55 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
+ # Cop supports --auto-correct.
11
+ # Configuration parameters: AllowForAlignment, EnforcedStyleForExponentOperator.
12
+ # SupportedStylesForExponentOperator: space, no_space
13
+ Layout/SpaceAroundOperators:
14
+ Exclude:
15
+ - '_x.rb'
16
+
17
+ # Offense count: 2
18
+ # Cop supports --auto-correct.
19
+ # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces.
20
+ # SupportedStyles: space, no_space, compact
21
+ # SupportedStylesForEmptyBraces: space, no_space
22
+ Layout/SpaceInsideHashLiteralBraces:
23
+ Exclude:
24
+ - '_x.rb'
25
+
26
+ # Offense count: 2
10
27
  # Configuration parameters: CountComments, Max, CountAsOne, ExcludedMethods, IgnoredMethods.
11
28
  # IgnoredMethods: refine
12
29
  Metrics/BlockLength:
@@ -14,6 +31,12 @@ Metrics/BlockLength:
14
31
  - '**/*.gemspec'
15
32
  - 'spec/atrea_control/duplex_spec.rb'
16
33
 
34
+ # Offense count: 1
35
+ # Configuration parameters: CountComments, Max, CountAsOne.
36
+ Metrics/ClassLength:
37
+ Exclude:
38
+ - 'lib/atrea_control/duplex.rb'
39
+
17
40
  # Offense count: 4
18
41
  # Configuration parameters: .
19
42
  # SupportedStyles: have_received, receive
@@ -31,7 +54,7 @@ RSpec/StubbedMock:
31
54
  Exclude:
32
55
  - 'spec/atrea_control/duplex_spec.rb'
33
56
 
34
- # Offense count: 4
57
+ # Offense count: 6
35
58
  RSpec/SubjectStub:
36
59
  Exclude:
37
60
  - 'spec/atrea_control/duplex_spec.rb'
@@ -44,14 +67,23 @@ Style/Documentation:
44
67
  - 'test/**/*'
45
68
  - 'lib/atrea_control.rb'
46
69
 
47
- # Offense count: 1
70
+ # Offense count: 2
48
71
  # Cop supports --auto-correct.
49
72
  # Configuration parameters: EnforcedStyle.
50
73
  # SupportedStyles: always, always_true, never
51
74
  Style/FrozenStringLiteralComment:
52
75
  Exclude:
76
+ - '_x.rb'
53
77
  - 'spec/atrea_control/duplex_spec.rb'
54
78
 
79
+ # Offense count: 2
80
+ # Cop supports --auto-correct.
81
+ # Configuration parameters: EnforcedStyle, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols.
82
+ # SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys
83
+ Style/HashSyntax:
84
+ Exclude:
85
+ - '_x.rb'
86
+
55
87
  # Offense count: 1
56
88
  # Cop supports --auto-correct.
57
89
  # Configuration parameters: EnforcedStyle.
@@ -60,9 +92,9 @@ Style/MutableConstant:
60
92
  Exclude:
61
93
  - 'spec/atrea_control/duplex_spec.rb'
62
94
 
63
- # Offense count: 1
95
+ # Offense count: 2
64
96
  # Cop supports --auto-correct.
65
- # Configuration parameters: AutoCorrect, Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
97
+ # Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
66
98
  # URISchemes: http, https
67
99
  Layout/LineLength:
68
100
  Exclude:
data/CHANGELOG.md CHANGED
@@ -1,4 +1,22 @@
1
1
  ## [Unreleased]
2
+ ## [1.3.1] - 2021-12-11
3
+ ### Changed
4
+ - version of selenium
5
+
6
+ ## [1.3.0] - 2021-12-11
7
+ ### Changed
8
+ - store auth tokens outside
9
+ - minimize selenium only for login
10
+
11
+ ## [1.2.1] - 2021-10-30
12
+ ### Changed
13
+ - login procedure
14
+ - ensure logged user by window.user object
15
+
16
+ ## [1.2.0] - 2021-10-26
17
+ ### Changed
18
+ - use internal unit.php for read values
19
+ - reload login automatically if session expire
2
20
  ## [1.1.0] - 2021-10-22
3
21
  ### Added
4
22
  - to_json
data/Gemfile CHANGED
@@ -5,8 +5,12 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in atrea_control.gemspec
6
6
  gemspec
7
7
 
8
+ gem "pry"
8
9
  gem "rake", "~> 13.0"
9
10
  gem "rspec", "~> 3.10"
10
11
  gem "rubocop", "~> 1.7", require: false
11
12
  gem "rubocop-rspec", "~> 2.4", require: false
12
- gem "simplecov", require: false, group: :test
13
+ group :test do
14
+ gem "simplecov", require: false
15
+ gem "webmock", "~> 3.14"
16
+ end
data/Gemfile.lock CHANGED
@@ -1,22 +1,54 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- atrea_control (1.1.0)
5
- selenium-webdriver (~> 3.142)
4
+ atrea_control (1.3.0)
5
+ nokogiri (~> 1.12)
6
+ rest-client (~> 2.1)
7
+ selenium-webdriver (~> 4.1)
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
- childprocess (3.0.0)
15
+ childprocess (4.1.0)
16
+ coderay (1.1.3)
17
+ crack (0.4.5)
18
+ rexml
12
19
  diff-lcs (1.4.4)
13
20
  docile (1.4.0)
14
- parallel (1.20.1)
15
- parser (3.0.2.0)
21
+ domain_name (0.5.20190701)
22
+ unf (>= 0.0.5, < 1.0.0)
23
+ hashdiff (1.0.1)
24
+ http-accept (1.7.0)
25
+ http-cookie (1.0.4)
26
+ domain_name (~> 0.5)
27
+ method_source (1.0.0)
28
+ mime-types (3.4.1)
29
+ mime-types-data (~> 3.2015)
30
+ mime-types-data (3.2021.1115)
31
+ netrc (0.11.0)
32
+ nokogiri (1.12.5-x86_64-darwin)
33
+ racc (~> 1.4)
34
+ nokogiri (1.12.5-x86_64-linux)
35
+ racc (~> 1.4)
36
+ parallel (1.21.0)
37
+ parser (3.0.3.2)
16
38
  ast (~> 2.4.1)
39
+ pry (0.14.1)
40
+ coderay (~> 1.1)
41
+ method_source (~> 1.0)
42
+ public_suffix (4.0.6)
43
+ racc (1.6.0)
17
44
  rainbow (3.0.0)
18
45
  rake (13.0.6)
19
- regexp_parser (2.1.1)
46
+ regexp_parser (2.2.0)
47
+ rest-client (2.1.0)
48
+ http-accept (>= 1.7.0, < 2.0)
49
+ http-cookie (>= 1.0.2, < 2.0)
50
+ mime-types (>= 1.16, < 4.0)
51
+ netrc (~> 0.8)
20
52
  rexml (3.2.5)
21
53
  rspec (3.10.0)
22
54
  rspec-core (~> 3.10.0)
@@ -30,25 +62,25 @@ GEM
30
62
  rspec-mocks (3.10.2)
31
63
  diff-lcs (>= 1.2.0, < 2.0)
32
64
  rspec-support (~> 3.10.0)
33
- rspec-support (3.10.2)
34
- rubocop (1.20.0)
65
+ rspec-support (3.10.3)
66
+ rubocop (1.23.0)
35
67
  parallel (~> 1.10)
36
68
  parser (>= 3.0.0.0)
37
69
  rainbow (>= 2.2.2, < 4.0)
38
70
  regexp_parser (>= 1.8, < 3.0)
39
71
  rexml
40
- rubocop-ast (>= 1.9.1, < 2.0)
72
+ rubocop-ast (>= 1.12.0, < 2.0)
41
73
  ruby-progressbar (~> 1.7)
42
74
  unicode-display_width (>= 1.4.0, < 3.0)
43
- rubocop-ast (1.11.0)
75
+ rubocop-ast (1.14.0)
44
76
  parser (>= 3.0.1.1)
45
- rubocop-rspec (2.4.0)
46
- rubocop (~> 1.0)
47
- rubocop-ast (>= 1.1.0)
77
+ rubocop-rspec (2.6.0)
78
+ rubocop (~> 1.19)
48
79
  ruby-progressbar (1.11.0)
49
80
  rubyzip (2.3.2)
50
- selenium-webdriver (3.142.7)
51
- childprocess (>= 0.5, < 4.0)
81
+ selenium-webdriver (4.1.0)
82
+ childprocess (>= 0.5, < 5.0)
83
+ rexml (~> 3.2, >= 3.2.5)
52
84
  rubyzip (>= 1.2.2)
53
85
  simplecov (0.21.2)
54
86
  docile (~> 1.1)
@@ -56,7 +88,14 @@ GEM
56
88
  simplecov_json_formatter (~> 0.1)
57
89
  simplecov-html (0.12.3)
58
90
  simplecov_json_formatter (0.1.3)
59
- unicode-display_width (2.0.0)
91
+ unf (0.1.4)
92
+ unf_ext
93
+ unf_ext (0.0.8)
94
+ unicode-display_width (2.1.0)
95
+ webmock (3.14.0)
96
+ addressable (>= 2.8.0)
97
+ crack (>= 0.3.2)
98
+ hashdiff (>= 0.4.0, < 2.0.0)
60
99
 
61
100
  PLATFORMS
62
101
  x86_64-darwin-19
@@ -64,11 +103,13 @@ PLATFORMS
64
103
 
65
104
  DEPENDENCIES
66
105
  atrea_control!
106
+ pry
67
107
  rake (~> 13.0)
68
108
  rspec (~> 3.10)
69
109
  rubocop (~> 1.7)
70
110
  rubocop-rspec (~> 2.4)
71
111
  simplecov
112
+ webmock (~> 3.14)
72
113
 
73
114
  BUNDLED WITH
74
115
  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 "selenium-webdriver", "~> 3.142"
37
+ spec.add_dependency "nokogiri", "~> 1.12"
38
+ spec.add_dependency "rest-client", "~> 2.1"
39
+ spec.add_dependency "selenium-webdriver", "~> 4.1"
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,12 @@ 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
+
17
+ attr_accessor :user_id, :unit_id, :auth_token
18
+
11
19
  # @param [String] login
12
20
  # @param [String] password
13
21
  # @param [Hash] sensors_map which box is related to sensor ID
@@ -15,27 +23,43 @@ module AtreaControl
15
23
  # @option sensors_map [String] :current_power
16
24
  # @option sensors_map [String] :current_mode
17
25
  def initialize(login:, password:, sensors_map: Config.default_sensors_map)
18
- @logged = false
19
26
  @login = login
20
27
  @password = password
21
28
  @sensors = sensors_map
22
29
  end
23
30
 
31
+ # @return [Selenium::WebDriver::Firefox::Driver]
24
32
  def driver
25
33
  return @driver if defined?(@driver)
26
34
 
27
35
  options = Selenium::WebDriver::Firefox::Options.new
28
36
  options.headless! unless ENV["NO_HEADLESS"]
29
- @driver ||= Selenium::WebDriver.for :firefox, options: options
37
+ @driver ||= Selenium::WebDriver.for :firefox, capabilities: [options]
30
38
  end
31
39
 
32
40
  def logged?
33
- @logged
41
+ user&.[] "loged"
42
+ end
43
+
44
+ def login_in_progress?
45
+ @login_in_progress
34
46
  end
35
47
 
36
48
  # Login into control
37
49
  def login
50
+ @login_in_progress = true
51
+ logger.debug "start new login"
38
52
  driver.get CONTROL_URI
53
+ submit_login_form unless logged?
54
+ finish_login
55
+ refresh!
56
+ inspect
57
+ ensure
58
+ @login_in_progress = false
59
+ end
60
+
61
+ # Submit given credentials and proceed login
62
+ def submit_login_form
39
63
  form = driver.find_element(id: "loginFrm")
40
64
  username = form.find_element(name: "username")
41
65
  username.send_keys @login
@@ -44,102 +68,161 @@ module AtreaControl
44
68
 
45
69
  submit = form.find_element(css: "input[type=submit]")
46
70
  submit.click
47
- finish_login
48
- inspect
49
71
  end
50
72
 
51
73
  # Retrieve dashboard URI from object tag and open it again
52
74
  def open_dashboard
53
75
  uri = driver.find_element(tag_name: "object").attribute "data"
54
76
  driver.get uri
77
+ user_id && unit_id && auth_token
55
78
  logger.debug "#{name} login success"
56
- @logged = true
57
79
  end
58
80
 
59
81
  # @return [String]
60
82
  def name
61
- return unless logged?
62
-
63
- container = driver.find_element css: "div#pageTitle > h2"
64
- container.text
65
- end
66
-
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
- end
74
-
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
81
- end
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
+ @name ||= driver.find_element(css: "div#pageTitle > h2")&.text if logged?
84
+ @name
85
+ end
86
+
87
+ # # @return [String] ID of logged user
88
+ # def user_id
89
+ # @user_id ||= driver.execute_script("return window._user")
90
+ # end
91
+ #
92
+ # # @return [String] ID of recuperation unit
93
+ # def unit_id
94
+ # @unit_id ||= driver.execute_script("return window._unit")
95
+ # end
96
+ #
97
+ # # @return [String] session token
98
+ # def auth_token
99
+ # @auth_token ||= user&.[]("auth")
100
+ # end
101
+
102
+ # Window.user object from atrea
103
+ # @return [Hash, nil]
104
+ def user
105
+ driver.execute_script("return window.user")
90
106
  end
91
107
 
92
108
  # @return [String]
93
- def current_mode
94
- return unless logged?
109
+ def current_mode_name
110
+ return current_mode unless logged?
95
111
 
96
- element = sensor_element(@sensors[__method__])
112
+ element = sensor_element(@sensors[:current_mode])
97
113
  element.find_element(css: "div:first-child").text
98
114
  end
99
115
 
100
116
  # quit selenium browser
101
117
  def close
102
- @logged = false
103
118
  driver.quit
119
+ ensure
120
+ remove_instance_variable :@driver
104
121
  end
105
122
 
123
+ alias logout! close
124
+
106
125
  def as_json(_options = nil)
107
126
  {
108
- logged: logged?,
109
127
  current_mode: current_mode,
110
128
  current_power: current_power,
111
129
  outdoor_temperature: outdoor_temperature,
130
+ valid_for: valid_for,
112
131
  }
113
132
  end
114
133
 
134
+ alias values as_json
135
+
115
136
  def to_json(*args)
116
137
  as_json.to_json(*args)
117
138
  end
118
139
 
119
- def inspect
120
- "<AtreaControl name: '#{name}' outdoor_temperature: #{outdoor_temperature}°C current_power: #{current_power}% current_mode: '#{current_mode}'>"
121
- end
140
+ # def inspect
141
+ # "<AtreaControl name: '#{name}' outdoor_temperature: '#{outdoor_temperature}°C' current_power: '#{current_power}%' current_mode: '#{current_mode}' valid_for: '#{valid_for}'>"
142
+ # end
122
143
 
144
+ def call_unit!
145
+ return false if @login_in_progress
146
+
147
+ logger.debug "call_unit!"
148
+ parse_response(response_comm_unit)
149
+ @valid_for = Time.now
150
+ as_json
151
+ end
123
152
 
124
153
  private
125
154
 
126
- def logger
127
- @logger ||= ::Logger.new($stdout)
155
+ # @see scripts.php -> loadRD5Values(node, init)
156
+ # @note
157
+ # if(values[key]>32767) values[key]-=65536;
158
+ # if(params[key] && params[key].offset)
159
+ # values[key]=values[key]-params[key].offset;
160
+ # if(params[key] && params[key].coef)
161
+ # values[key]=values[key]/params[key].coef;
162
+ def parse_response(response)
163
+ xml = Nokogiri::XML response.body
164
+ sensors_values = @sensors.transform_values do |id|
165
+ value = xml.xpath("//O[@I=\"#{id}\"]/@V").last&.value.to_i
166
+ value -= 65_536 if value > 32_767
167
+ # value -= 0 if "offset"
168
+ # value -= 0 if "coef"
169
+ value
170
+ end
171
+ refresh_data(sensors_values)
128
172
  end
129
173
 
130
- def sensor_element(sensor_id)
131
- driver.find_element id: "contentBox#{sensor_id}"
174
+ # @param [Hash] values
175
+ # @return [Hash]
176
+ def refresh_data(values)
177
+ @outdoor_temperature = values[:outdoor_temperature].to_f / 10.0
178
+ @current_power = values[:current_power].to_f
179
+ @current_mode = mode_map[values[:current_mode]]
180
+
181
+ as_json
182
+ end
183
+
184
+ # ? I10204 ?
185
+ def mode_map
186
+ { 0 => "Vypnuto", 1 => "Automat", 2 => "Větrání", 6 => "Rozvážení" }
187
+ end
188
+
189
+ def logger
190
+ @logger ||= ::Logger.new($stdout)
132
191
  end
133
192
 
134
193
  def finish_login
135
194
  13.times do |i|
136
195
  return true if open_dashboard
137
196
  rescue Selenium::WebDriver::Error::NoSuchElementError => _e
138
- t = [5 * (1 + i), 25].min
197
+ t = [3 * (1 + i), 25].min
139
198
  logger.debug "waiting #{t}s for login..."
140
199
  sleep t
141
200
  end
142
201
  raise Error, "unable to login"
143
202
  end
203
+
204
+ def sensor_element(sensor_id)
205
+ driver.find_element id: "contentBox#{sensor_id}"
206
+ end
207
+
208
+ # @return [RestClient::Response]
209
+ def response_comm_unit
210
+ params = {
211
+ _user: user_id.to_i,
212
+ _unit: unit_id,
213
+ auth: auth_token || "null",
214
+ _t: "config/xml.xml",
215
+ }
216
+ autologin_token = CGI.escape([@login, @password].join("\b"))
217
+ RestClient.get "https://control.atrea.eu/comm/sw/unit.php", { Cookie: "autoLogin=#{autologin_token}", params: params }
218
+ end
219
+
220
+ # Update tokens based on current state
221
+ def refresh!
222
+ @user_id = driver.execute_script("return window._user")
223
+ @unit_id = driver.execute_script("return window._unit")
224
+ @auth_token = user&.[]("auth")
225
+ end
226
+
144
227
  end
145
228
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AtreaControl
4
- VERSION = "1.1.0"
4
+
5
+ VERSION = "1.3.1"
6
+
5
7
  end
metadata CHANGED
@@ -1,29 +1,57 @@
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.3.1
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-12-11 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
16
44
  requirements:
17
45
  - - "~>"
18
46
  - !ruby/object:Gem::Version
19
- version: '3.142'
47
+ version: '4.1'
20
48
  type: :runtime
21
49
  prerelease: false
22
50
  version_requirements: !ruby/object:Gem::Requirement
23
51
  requirements:
24
52
  - - "~>"
25
53
  - !ruby/object:Gem::Version
26
- version: '3.142'
54
+ version: '4.1'
27
55
  description: Read data from web controller of RD5 duplex by Atrea.
28
56
  email:
29
57
  - pokorny@luk4s.cz