atrea_control 2.3.0 → 3.0.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/main.yml +6 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +30 -15
- data/.ruby-version +1 -1
- data/CHANGELOG.md +10 -0
- data/Gemfile.lock +28 -35
- data/README.md +23 -33
- data/atrea_control.gemspec +0 -1
- data/bin/console +4 -4
- data/lib/atrea_control/duplex/login.rb +89 -87
- data/lib/atrea_control/duplex/request.rb +1 -0
- data/lib/atrea_control/duplex/unit.rb +20 -7
- data/lib/atrea_control/duplex/user_ctrl.rb +1 -1
- data/lib/atrea_control/duplex.rb +1 -1
- data/lib/atrea_control/sensor_parser.rb +3 -2
- data/lib/atrea_control/version.rb +2 -1
- data/lib/atrea_control.rb +6 -0
- metadata +3 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 919ab4f4ed1dde112816e58cecfb4ffc393cb539cecf81796a2490219683c75d
|
4
|
+
data.tar.gz: 7b450714f08130ad30ad565c5ce04b22b29435c43cd8230dbf10103a04c9e624
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 360fc2c895cc21dabffd4450a5013899263077b7a9f5c968c7046584728e457f795e8a159dc714021ac2dfaed2b5fe3792debd67c88c52810144d83bea792cff
|
7
|
+
data.tar.gz: bfdd992e729adccf960aee9d26e9088ef9fe7beb20f1067396099248659c187e079f303504e04fefb7bdac9dee0dd0249f01c053b39966cef67f55c2da2ada69
|
data/.github/workflows/main.yml
CHANGED
@@ -1,17 +1,19 @@
|
|
1
1
|
name: Ruby
|
2
2
|
|
3
|
-
on: [push,pull_request]
|
3
|
+
on: [push, pull_request]
|
4
4
|
|
5
5
|
jobs:
|
6
6
|
spec:
|
7
7
|
runs-on: ubuntu-latest
|
8
|
+
strategy:
|
9
|
+
matrix:
|
10
|
+
ruby-version: [3.2, 3.3, 3]
|
8
11
|
steps:
|
9
12
|
- uses: actions/checkout@v4
|
10
13
|
- name: Set up Ruby
|
11
14
|
uses: ruby/setup-ruby@v1
|
12
15
|
with:
|
13
|
-
ruby-version:
|
16
|
+
ruby-version: ${{ matrix.ruby-version }}
|
14
17
|
bundler-cache: true
|
15
|
-
- uses: browser-actions/setup-firefox@latest
|
16
18
|
- name: Run tests
|
17
|
-
run: bundle exec rspec
|
19
|
+
run: bundle exec rspec
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
@@ -1,17 +1,24 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on
|
3
|
+
# on 2025-01-24 16:50:34 UTC using RuboCop version 1.70.0.
|
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:
|
9
|
+
# Offense count: 1
|
10
|
+
# Configuration parameters: Severity, Include.
|
11
|
+
# Include: **/*.gemspec
|
12
|
+
Gemspec/RequiredRubyVersion:
|
13
|
+
Exclude:
|
14
|
+
- 'atrea_control.gemspec'
|
15
|
+
|
16
|
+
# Offense count: 5
|
10
17
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
11
18
|
Metrics/AbcSize:
|
12
19
|
Max: 34
|
13
20
|
|
14
|
-
# Offense count:
|
21
|
+
# Offense count: 3
|
15
22
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
16
23
|
Metrics/MethodLength:
|
17
24
|
Max: 21
|
@@ -28,28 +35,30 @@ RSpec/ExpectInHook:
|
|
28
35
|
Exclude:
|
29
36
|
- 'spec/atrea_control/duplex/unit_spec.rb'
|
30
37
|
|
31
|
-
# Offense count:
|
32
|
-
# Configuration parameters:
|
38
|
+
# Offense count: 4
|
39
|
+
# Configuration parameters: .
|
33
40
|
# SupportedStyles: have_received, receive
|
34
41
|
RSpec/MessageSpies:
|
35
|
-
|
36
|
-
- 'spec/atrea_control/duplex/login_spec.rb'
|
37
|
-
- 'spec/atrea_control/duplex/unit_spec.rb'
|
42
|
+
EnforcedStyle: receive
|
38
43
|
|
39
|
-
# Offense count:
|
44
|
+
# Offense count: 1
|
40
45
|
RSpec/MultipleExpectations:
|
41
46
|
Max: 3
|
42
47
|
|
43
|
-
# Offense count:
|
48
|
+
# Offense count: 4
|
49
|
+
# This cop supports unsafe autocorrection (--autocorrect-all).
|
50
|
+
RSpec/ReceiveMessages:
|
51
|
+
Exclude:
|
52
|
+
- 'spec/atrea_control/duplex/unit_spec.rb'
|
53
|
+
|
54
|
+
# Offense count: 1
|
44
55
|
RSpec/StubbedMock:
|
45
56
|
Exclude:
|
46
|
-
- 'spec/atrea_control/duplex/login_spec.rb'
|
47
57
|
- 'spec/atrea_control/duplex/unit_spec.rb'
|
48
58
|
|
49
|
-
# Offense count:
|
59
|
+
# Offense count: 9
|
50
60
|
RSpec/SubjectStub:
|
51
61
|
Exclude:
|
52
|
-
- 'spec/atrea_control/duplex/login_spec.rb'
|
53
62
|
- 'spec/atrea_control/duplex/unit_spec.rb'
|
54
63
|
- 'spec/atrea_control/duplex/user_ctrl_spec.rb'
|
55
64
|
|
@@ -57,7 +66,6 @@ RSpec/SubjectStub:
|
|
57
66
|
# Configuration parameters: IgnoreNameless, IgnoreSymbolicNames.
|
58
67
|
RSpec/VerifiedDoubles:
|
59
68
|
Exclude:
|
60
|
-
- 'spec/atrea_control/duplex/login_spec.rb'
|
61
69
|
- 'spec/atrea_control/duplex/unit_spec.rb'
|
62
70
|
- 'spec/atrea_control/duplex/user_ctrl_spec.rb'
|
63
71
|
|
@@ -66,7 +74,7 @@ Security/Eval:
|
|
66
74
|
Exclude:
|
67
75
|
- 'lib/atrea_control/duplex/user_ctrl.rb'
|
68
76
|
|
69
|
-
# Offense count:
|
77
|
+
# Offense count: 3
|
70
78
|
# Configuration parameters: AllowedConstants.
|
71
79
|
Style/Documentation:
|
72
80
|
Exclude:
|
@@ -74,3 +82,10 @@ Style/Documentation:
|
|
74
82
|
- 'test/**/*'
|
75
83
|
- 'lib/atrea_control.rb'
|
76
84
|
- 'lib/atrea_control/logger.rb'
|
85
|
+
|
86
|
+
# Offense count: 9
|
87
|
+
# This cop supports safe autocorrection (--autocorrect).
|
88
|
+
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
|
89
|
+
# URISchemes: http, https
|
90
|
+
Layout/LineLength:
|
91
|
+
Max: 238
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.3.
|
1
|
+
3.3.6
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,14 @@
|
|
1
1
|
## [Unreleased]
|
2
|
+
## [3.0.0] - 2025-01-25
|
3
|
+
### Removed
|
4
|
+
- selenium-based login procedure
|
5
|
+
### Added
|
6
|
+
- token / phpsessionid-based login in background
|
7
|
+
- "session" validity check & expiration (exception)
|
8
|
+
### Changed
|
9
|
+
- ruby version 3.3+
|
10
|
+
-
|
11
|
+
## [2.2.0] - 2024-10-20
|
2
12
|
### Added
|
3
13
|
- timestamp from atrea server
|
4
14
|
### Changed
|
data/Gemfile.lock
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
atrea_control (
|
4
|
+
atrea_control (3.0.0)
|
5
5
|
i18n (~> 1.14)
|
6
6
|
nokogiri (~> 1.15)
|
7
7
|
rest-client (~> 2.1)
|
8
|
-
selenium-webdriver (~> 4.25.0)
|
9
8
|
|
10
9
|
GEM
|
11
10
|
remote: https://rubygems.org/
|
@@ -13,55 +12,54 @@ GEM
|
|
13
12
|
addressable (2.8.7)
|
14
13
|
public_suffix (>= 2.0.2, < 7.0)
|
15
14
|
ast (2.4.2)
|
16
|
-
|
17
|
-
bigdecimal (3.1.8)
|
15
|
+
bigdecimal (3.1.9)
|
18
16
|
coderay (1.1.3)
|
19
|
-
concurrent-ruby (1.3.
|
17
|
+
concurrent-ruby (1.3.5)
|
20
18
|
crack (1.0.0)
|
21
19
|
bigdecimal
|
22
20
|
rexml
|
23
21
|
diff-lcs (1.5.1)
|
24
22
|
docile (1.4.1)
|
25
23
|
domain_name (0.6.20240107)
|
26
|
-
hashdiff (1.1.
|
24
|
+
hashdiff (1.1.2)
|
27
25
|
http-accept (1.7.0)
|
28
|
-
http-cookie (1.0.
|
26
|
+
http-cookie (1.0.8)
|
29
27
|
domain_name (~> 0.5)
|
30
|
-
i18n (1.14.
|
28
|
+
i18n (1.14.7)
|
31
29
|
concurrent-ruby (~> 1.0)
|
32
|
-
json (2.
|
30
|
+
json (2.9.1)
|
33
31
|
language_server-protocol (3.17.0.3)
|
34
|
-
logger (1.6.
|
32
|
+
logger (1.6.5)
|
35
33
|
method_source (1.1.0)
|
36
34
|
mime-types (3.6.0)
|
37
35
|
logger
|
38
36
|
mime-types-data (~> 3.2015)
|
39
|
-
mime-types-data (3.
|
37
|
+
mime-types-data (3.2025.0107)
|
40
38
|
netrc (0.11.0)
|
41
|
-
nokogiri (1.
|
39
|
+
nokogiri (1.18.2-arm64-darwin)
|
42
40
|
racc (~> 1.4)
|
43
|
-
nokogiri (1.
|
41
|
+
nokogiri (1.18.2-x86_64-darwin)
|
44
42
|
racc (~> 1.4)
|
45
|
-
nokogiri (1.
|
43
|
+
nokogiri (1.18.2-x86_64-linux-gnu)
|
46
44
|
racc (~> 1.4)
|
47
45
|
parallel (1.26.3)
|
48
|
-
parser (3.3.
|
46
|
+
parser (3.3.7.0)
|
49
47
|
ast (~> 2.4.1)
|
50
48
|
racc
|
51
|
-
pry (0.
|
49
|
+
pry (0.15.2)
|
52
50
|
coderay (~> 1.1)
|
53
51
|
method_source (~> 1.0)
|
54
52
|
public_suffix (6.0.1)
|
55
53
|
racc (1.8.1)
|
56
54
|
rainbow (3.1.1)
|
57
55
|
rake (13.2.1)
|
58
|
-
regexp_parser (2.
|
56
|
+
regexp_parser (2.10.0)
|
59
57
|
rest-client (2.1.0)
|
60
58
|
http-accept (>= 1.7.0, < 2.0)
|
61
59
|
http-cookie (>= 1.0.2, < 2.0)
|
62
60
|
mime-types (>= 1.16, < 4.0)
|
63
61
|
netrc (~> 0.8)
|
64
|
-
rexml (3.
|
62
|
+
rexml (3.4.0)
|
65
63
|
rspec (3.13.0)
|
66
64
|
rspec-core (~> 3.13.0)
|
67
65
|
rspec-expectations (~> 3.13.0)
|
@@ -74,45 +72,40 @@ GEM
|
|
74
72
|
rspec-mocks (3.13.2)
|
75
73
|
diff-lcs (>= 1.2.0, < 2.0)
|
76
74
|
rspec-support (~> 3.13.0)
|
77
|
-
rspec-support (3.13.
|
78
|
-
rubocop (1.
|
75
|
+
rspec-support (3.13.2)
|
76
|
+
rubocop (1.70.0)
|
79
77
|
json (~> 2.3)
|
80
78
|
language_server-protocol (>= 3.17.0)
|
81
79
|
parallel (~> 1.10)
|
82
80
|
parser (>= 3.3.0.2)
|
83
81
|
rainbow (>= 2.2.2, < 4.0)
|
84
|
-
regexp_parser (>= 2.
|
85
|
-
rubocop-ast (>= 1.
|
82
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
83
|
+
rubocop-ast (>= 1.36.2, < 2.0)
|
86
84
|
ruby-progressbar (~> 1.7)
|
87
|
-
unicode-display_width (>= 2.4.0, <
|
88
|
-
rubocop-ast (1.
|
85
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
86
|
+
rubocop-ast (1.37.0)
|
89
87
|
parser (>= 3.3.1.0)
|
90
|
-
rubocop-rspec (3.
|
88
|
+
rubocop-rspec (3.4.0)
|
91
89
|
rubocop (~> 1.61)
|
92
90
|
ruby-progressbar (1.13.0)
|
93
|
-
rubyzip (2.3.2)
|
94
|
-
selenium-webdriver (4.25.0)
|
95
|
-
base64 (~> 0.2)
|
96
|
-
logger (~> 1.4)
|
97
|
-
rexml (~> 3.2, >= 3.2.5)
|
98
|
-
rubyzip (>= 1.2.2, < 3.0)
|
99
|
-
websocket (~> 1.0)
|
100
91
|
simplecov (0.22.0)
|
101
92
|
docile (~> 1.1)
|
102
93
|
simplecov-html (~> 0.11)
|
103
94
|
simplecov_json_formatter (~> 0.1)
|
104
95
|
simplecov-html (0.13.1)
|
105
96
|
simplecov_json_formatter (0.1.4)
|
106
|
-
unicode-display_width (
|
97
|
+
unicode-display_width (3.1.4)
|
98
|
+
unicode-emoji (~> 4.0, >= 4.0.4)
|
99
|
+
unicode-emoji (4.0.4)
|
107
100
|
webmock (3.24.0)
|
108
101
|
addressable (>= 2.8.0)
|
109
102
|
crack (>= 0.3.2)
|
110
103
|
hashdiff (>= 0.4.0, < 2.0.0)
|
111
|
-
websocket (1.2.11)
|
112
104
|
|
113
105
|
PLATFORMS
|
114
106
|
arm64-darwin-22
|
115
107
|
arm64-darwin-23
|
108
|
+
arm64-darwin-24
|
116
109
|
x86_64-darwin-20
|
117
110
|
x86_64-linux
|
118
111
|
|
@@ -127,4 +120,4 @@ DEPENDENCIES
|
|
127
120
|
webmock (~> 3.14)
|
128
121
|
|
129
122
|
BUNDLED WITH
|
130
|
-
2.
|
123
|
+
2.6.3
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# atrea_control
|
2
2
|
Ventilation systems by https://www.atrea.eu are build with web UI portal - but this portal did not provide any API interface...
|
3
3
|
|
4
|
-
This gem provide
|
4
|
+
This gem provide way how to connect to portal and obtain data from unit as API.
|
5
5
|
|
6
6
|
## Highlights
|
7
7
|
|
@@ -19,25 +19,38 @@ This gem provide simple DSL by parsing content of https://control.atrea.eu with
|
|
19
19
|
Add this line to your application's Gemfile:
|
20
20
|
|
21
21
|
```ruby
|
22
|
-
gem
|
22
|
+
gem "atrea_control"
|
23
23
|
```
|
24
24
|
|
25
25
|
And then execute:
|
26
|
+
```bash
|
27
|
+
bundle install
|
28
|
+
```
|
26
29
|
|
27
|
-
|
30
|
+
Or
|
31
|
+
```bash
|
32
|
+
bundle add atrea_control
|
33
|
+
```
|
28
34
|
|
29
35
|
Or install it yourself as:
|
30
36
|
|
31
|
-
|
37
|
+
```bash
|
38
|
+
gem install atrea_control
|
39
|
+
```
|
32
40
|
|
33
41
|
## Usage
|
34
42
|
|
35
43
|
At the begin you need obtain `user_id`, `unit_id` and `sid` (auth token). For this use "Login"
|
44
|
+
|
45
|
+
* `user_id` is atrea internal ID of user account
|
46
|
+
* `unit_id` is atrea `ident` - identification number of airflow unit (ventilation system) - 10 digits
|
47
|
+
* `sid` is session ID - auth token, valid for logged session. Its validity is unknown
|
48
|
+
|
36
49
|
```ruby
|
37
50
|
tokens = AtreaControl::Duplex::Login.user_tokens login: "myhome", password: "sup3r-S3CR3T-kocicka"
|
38
51
|
tokens # => { user_id: "1234", unit_id: "85425324672", sid: 4012 }
|
39
52
|
```
|
40
|
-
I recommend to store then somewhere...
|
53
|
+
I recommend to store then somewhere...
|
41
54
|
Then you can call Unit for data...
|
42
55
|
|
43
56
|
Example usage:
|
@@ -46,6 +59,7 @@ control = AtreaControl::Duplex::Unit.new user_id: "1234", unit_id: "85425324672"
|
|
46
59
|
control.values # => { current_power: 88.0, current_mode: "CO2" }
|
47
60
|
control.power # => 88.0
|
48
61
|
```
|
62
|
+
|
49
63
|
### Dig deeper
|
50
64
|
`AtreaControl::Duplex::Unit` expect optional argument `user_ctrl` which should be object respond to
|
51
65
|
|
@@ -56,36 +70,12 @@ control.power # => 88.0
|
|
56
70
|
|
57
71
|
__Please check [lib/atrea_control/duplex/user_ctrl.rb](./lib/atrea_control/duplex/user_ctrl.rb) for more details !__
|
58
72
|
|
59
|
-
|
60
|
-
Login is currently done by selenium - fill login form.
|
61
|
-
I found that Atre submit form to BE, generate some "empty" HTML and JS which onLoad start doing request to queue for "login".
|
62
|
-
|
63
|
-
Re-login user, add login procedure into queue:
|
64
|
-
```bash
|
65
|
-
curl -X POST -d "comm=config%2Flogin.cgi" "https://control.atrea.eu/apps/rd5Control/handle.php?action=unitLogin&user=XXXX&unit=NNNNNNN&table=userUnits&idPwd=YYYYYYY&NFP"
|
66
|
-
```
|
67
|
-
Response is time in seconds when login will ready:
|
68
|
-
```xml
|
69
|
-
<root><sended time="264"/></root>
|
70
|
-
```
|
71
|
-
Based it su shown countdown ...
|
72
|
-
|
73
|
-
|
74
|
-
Request for current queue status
|
75
|
-
```bash
|
76
|
-
curl 'https://control.atrea.eu/apps/rd5Control/handle.php?Sync=1&action=unitQuery&query=loged&user=XXXX&unit=NNNNNNN'
|
77
|
-
```
|
78
|
-
if queue is processed:
|
79
|
-
```xml
|
80
|
-
<root><login uconn="16395889" sid="010101" ver="3001009"/></root>
|
81
|
-
```
|
82
|
-
else
|
83
|
-
```xml
|
84
|
-
<root><login uconn="16390480" sid="0"/></root>
|
85
|
-
```
|
73
|
+
This object is used to translate internal unit modes to user-friendly texts & translations.
|
86
74
|
|
87
|
-
|
75
|
+
I strong recommend to use `AtreaControl::Duplex::UserCtrl` object from "cache",
|
76
|
+
for optimize network traffic - because they are static data.
|
88
77
|
|
78
|
+
## Development
|
89
79
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
90
80
|
|
91
81
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
data/atrea_control.gemspec
CHANGED
data/bin/console
CHANGED
@@ -8,8 +8,8 @@ require "atrea_control"
|
|
8
8
|
# with your gem easier. You can also use a different console, if you like.
|
9
9
|
|
10
10
|
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
-
|
12
|
-
|
11
|
+
require "pry"
|
12
|
+
Pry.start
|
13
13
|
|
14
|
-
require "irb"
|
15
|
-
IRB.start(__FILE__)
|
14
|
+
# require "irb"
|
15
|
+
# IRB.start(__FILE__)
|
@@ -1,23 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "nokogiri"
|
4
4
|
require "rest-client"
|
5
|
-
require "
|
5
|
+
require "securerandom"
|
6
6
|
|
7
7
|
module AtreaControl
|
8
8
|
module Duplex
|
9
|
-
# Process login into RD5
|
9
|
+
# Process login into RD5 to get `sid` ( auth_token ) for direct API communication
|
10
10
|
class Login
|
11
11
|
include AtreaControl::Logger
|
12
12
|
|
13
13
|
# @return [Hash] - user_id, unit_id, sid
|
14
14
|
def self.user_tokens(login:, password:)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
tokens
|
19
|
-
ensure
|
20
|
-
i.close
|
15
|
+
instance = new(login: login, password: password)
|
16
|
+
instance.call
|
21
17
|
end
|
22
18
|
|
23
19
|
# @param [String] login
|
@@ -26,101 +22,107 @@ module AtreaControl
|
|
26
22
|
@login = login
|
27
23
|
@password = password
|
28
24
|
end
|
29
|
-
#
|
30
|
-
# def crypto_password
|
31
|
-
# md5 = Digest::MD5.new
|
32
|
-
# md5 << "\r\n"
|
33
|
-
# md5 << @password
|
34
|
-
# md5.hexdigest
|
35
|
-
# end
|
36
|
-
#
|
37
|
-
# def token
|
38
|
-
# RestClient.get "#{AtreaControl::Duplex::CONTROL_URI}/config/login.cgi", params: { magic: crypto_password }
|
39
|
-
# end
|
40
25
|
|
41
|
-
|
42
|
-
|
26
|
+
# Perform login procedure for retrieve `sid` (auth_token)
|
27
|
+
# @return [Hash] - user_id, unit_id, sid
|
28
|
+
# @raise [AtreaControl::Error] if login failed
|
29
|
+
def call
|
30
|
+
@sid = sid
|
31
|
+
if @sid == "0"
|
32
|
+
re_login = RestClient.post "#{AtreaControl::Duplex::CONTROL_URI}/apps/rd5Control/handle.php?action=unitLogin&user=#{user_id}&unit=#{unit_id}&table=userUnits&idPwd=#{unit[:iid]}&#{SecureRandom.hex(2)}&_ts=#{SecureRandom.hex(4)}",
|
33
|
+
{ comm: "config/login.cgi?magic=" }, headers
|
34
|
+
time = Nokogiri::XML(re_login.body).at_xpath("//sended")["time"].to_i
|
35
|
+
logger.debug "Login in #{time} seconds..."
|
36
|
+
time.times do
|
37
|
+
@sid = sid
|
38
|
+
break if @sid != "0"
|
39
|
+
|
40
|
+
sleep 1
|
41
|
+
end
|
42
|
+
raise AtreaControl::Error, "Login failed" if @sid == "0"
|
43
|
+
|
44
|
+
logger.debug "Login complete !"
|
45
|
+
else
|
46
|
+
logger.debug "Login is not necessary ! SID: #{@sid}"
|
47
|
+
end
|
48
|
+
{ user_id:, unit_id:, sid: @sid }
|
49
|
+
end
|
43
50
|
|
44
|
-
|
45
|
-
@user_id = driver.execute_script("return window._user")
|
46
|
-
@unit_id = driver.execute_script("return window._unit")
|
47
|
-
@auth_token = driver.execute_script("return window.user")&.[]("auth") # sid
|
51
|
+
private
|
48
52
|
|
49
|
-
|
50
|
-
end
|
53
|
+
# @!group Login steps, order is important
|
51
54
|
|
52
|
-
#
|
53
|
-
|
54
|
-
|
55
|
+
# Retrieve user details from RD5 core.php?action=init
|
56
|
+
# @return [Hash] - user_id, name
|
57
|
+
def user
|
58
|
+
core_init = RestClient.get "#{AtreaControl::Duplex::CONTROL_URI}/core/core.php?action=init&_ts=#{SecureRandom.hex(4)}",
|
59
|
+
headers
|
60
|
+
client = Nokogiri::XML(core_init.body).at_xpath("//client")
|
61
|
+
user_id = client["id"]
|
62
|
+
name = client["name"]
|
63
|
+
logger.debug "User ID: #{user_id}, User Name: #{name}"
|
64
|
+
|
65
|
+
{ user_id:, name: }
|
66
|
+
end
|
55
67
|
|
56
|
-
|
57
|
-
|
58
|
-
# @driver ||= Selenium::WebDriver.for :firefox, capabilities: [options]
|
59
|
-
options = Selenium::WebDriver::Firefox::Options.new
|
60
|
-
options.add_argument "-headless" unless ENV["NO_HEADLESS"]
|
61
|
-
@driver ||= Selenium::WebDriver::Firefox::Driver.new options: options
|
68
|
+
def user_id
|
69
|
+
@user_id ||= user[:user_id]
|
62
70
|
end
|
63
71
|
|
64
|
-
#
|
65
|
-
def
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
driver.get "#{AtreaControl::Duplex::CONTROL_URI}?action=logout"
|
71
|
-
submit_login_form
|
72
|
-
finish_login
|
73
|
-
driver
|
74
|
-
ensure
|
75
|
-
@login_in_progress = false
|
72
|
+
# For some reason, this requests must be done before `unit_id` requested
|
73
|
+
def run_rd5_app
|
74
|
+
RestClient.post "#{AtreaControl::Duplex::CONTROL_URI}/core/core.php?Sync=1&action=run&object=app&lng=28&rVer=1&_ts=#{SecureRandom.hex(4)}",
|
75
|
+
{ name: "rd5Control", path: "apps/rd5Control/" }, headers
|
76
|
+
RestClient.post "#{AtreaControl::Duplex::CONTROL_URI}/core/core.php?Sync=1&action=load&object=setting&_ts=#{SecureRandom.hex(4)}",
|
77
|
+
{ path: "apps/rd5Control" }, headers
|
76
78
|
end
|
77
79
|
|
78
|
-
#
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
80
|
+
# Retrieve overview of RD5 unit
|
81
|
+
# @return [Hash] - unit_number (digit code/ID from list) and iid (unit salt?)
|
82
|
+
def unit
|
83
|
+
return @unit if @unit
|
84
|
+
|
85
|
+
# run_rd5_app
|
86
|
+
units_table = RestClient.get "#{AtreaControl::Duplex::CONTROL_URI}/_data/data.php?Sync=1&action=getdata&rH&rE&table=userUnits&ds=rd5&_ts=#{SecureRandom.hex(4)}",
|
87
|
+
headers
|
88
|
+
item = Nokogiri::XML(units_table.body).at_xpath("//i")
|
89
|
+
unit_number = item["unit"]
|
90
|
+
iid = item["id"]
|
91
|
+
@unit ||= { unit_number:, iid: }
|
89
92
|
end
|
90
93
|
|
91
|
-
#
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
94
|
+
# With `unit_number` from `unit` method, get `unit_id` from RD5 unit records
|
95
|
+
# @return [String] - unit_id
|
96
|
+
def unit_id
|
97
|
+
return @unit_id if @unit_id
|
98
|
+
|
99
|
+
records = RestClient.get "#{AtreaControl::Duplex::CONTROL_URI}/_data/data.php?Sync=1&action=getrecord&id=#{unit[:unit_number]}&table=units&ds=rd5&_ts=#{SecureRandom.hex(4)}",
|
100
|
+
headers
|
101
|
+
@unit_id ||= Nokogiri::XML(records.body).at_xpath("//table/i")["ident"]
|
98
102
|
end
|
99
103
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
nil
|
106
|
-
end
|
107
|
-
logger.debug "driver closed & destroyed"
|
108
|
-
ensure
|
109
|
-
remove_instance_variable :@driver
|
104
|
+
def sid
|
105
|
+
data = RestClient.get "#{AtreaControl::Duplex::CONTROL_URI}/apps/rd5Control/handle.php?Sync=1&action=unitQuery&query=loged&user=#{user_id}&unit=#{unit_id}&#{SecureRandom.hex(2)}&_ts=#{SecureRandom.hex(4)}",
|
106
|
+
headers
|
107
|
+
logger.debug data.body
|
108
|
+
Nokogiri::XML(data.body).at_xpath("//login")["sid"]
|
110
109
|
end
|
111
110
|
|
112
|
-
|
111
|
+
# @!group Private methods
|
113
112
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
113
|
+
# @return [String] session ID from PHP BE
|
114
|
+
def php_session_id
|
115
|
+
return @php_session_id if @php_session_id
|
116
|
+
|
117
|
+
payload = { username: @login, password: @password }
|
118
|
+
RestClient.post "#{AtreaControl::Duplex::CONTROL_URI}?action=login", payload do |response|
|
119
|
+
@php_session_id = response.cookies["PHPSESSID"]
|
121
120
|
end
|
122
|
-
|
123
|
-
|
121
|
+
@php_session_id
|
122
|
+
end
|
123
|
+
|
124
|
+
def headers
|
125
|
+
{ cookies: { PHPSESSID: php_session_id }, "App-name": "rd5Control" }
|
124
126
|
end
|
125
127
|
end
|
126
128
|
end
|
@@ -9,8 +9,6 @@ module AtreaControl
|
|
9
9
|
attr_reader :current_mode, :current_power, :outdoor_temperature, :preheat_temperature, :input_temperature
|
10
10
|
# @return [Boolean] preheating air is ON ?
|
11
11
|
attr_reader :preheating
|
12
|
-
# @return [DateTime] store time of last update
|
13
|
-
attr_reader :valid_for
|
14
12
|
# @return [UserCtrl]
|
15
13
|
attr_reader :user_ctrl
|
16
14
|
# @return [Time, DateTime]
|
@@ -69,6 +67,8 @@ module AtreaControl
|
|
69
67
|
parsed.each do |name, value|
|
70
68
|
instance_variable_set :"@#{name}", value
|
71
69
|
end
|
70
|
+
raise AtreaControl::SessionExpired unless valid?
|
71
|
+
|
72
72
|
as_json
|
73
73
|
end
|
74
74
|
|
@@ -80,7 +80,6 @@ module AtreaControl
|
|
80
80
|
preheat_temperature: preheat_temperature,
|
81
81
|
input_temperature: input_temperature,
|
82
82
|
preheating: preheating,
|
83
|
-
valid_for: valid_for,
|
84
83
|
timestamp: timestamp,
|
85
84
|
}
|
86
85
|
end
|
@@ -89,15 +88,29 @@ module AtreaControl
|
|
89
88
|
values.to_json(*)
|
90
89
|
end
|
91
90
|
|
92
|
-
#
|
93
|
-
# @
|
91
|
+
# Expire cached data and fetch them again
|
92
|
+
# @return [Hash] new values
|
93
|
+
def refresh!
|
94
|
+
remove_instance_variable(:@parsed) if defined?(@parsed)
|
95
|
+
values
|
96
|
+
end
|
97
|
+
|
98
|
+
# Data are valid if timestamp within 15.minutes
|
99
|
+
def valid?
|
100
|
+
return false unless timestamp
|
101
|
+
|
102
|
+
timestamp > (Time.now - (15 * 60.0))
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
# Additional "parameters" for each sensor
|
108
|
+
# @note it's changed in time ?
|
94
109
|
def params
|
95
110
|
response = request.call(_t: "user/params.xml")
|
96
111
|
Nokogiri::XML response.body
|
97
112
|
end
|
98
113
|
|
99
|
-
private
|
100
|
-
|
101
114
|
def parser
|
102
115
|
@parser ||= ::AtreaControl::SensorParser.new(@user_ctrl)
|
103
116
|
end
|
data/lib/atrea_control/duplex.rb
CHANGED
@@ -4,7 +4,7 @@ module AtreaControl
|
|
4
4
|
# Controller for +control.atrea.eu+
|
5
5
|
module Duplex
|
6
6
|
CONTROL_URI = "https://control.atrea.eu/"
|
7
|
-
CONTROL_VERSION = "
|
7
|
+
CONTROL_VERSION = "003001022"
|
8
8
|
|
9
9
|
autoload :Login, "atrea_control/duplex/login"
|
10
10
|
autoload :Request, "atrea_control/duplex/request"
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "nokogiri"
|
4
|
+
require "time"
|
4
5
|
|
5
6
|
module AtreaControl
|
6
7
|
# Call RD5 unit ang get current sensors values
|
@@ -43,6 +44,7 @@ module AtreaControl
|
|
43
44
|
preheating = %w[C10200 C10202 C10215 C10217].any? do |i|
|
44
45
|
xml.xpath("//O[@I=\"#{i}\"]/@V").last&.value == "1"
|
45
46
|
end
|
47
|
+
# @note timestamp seems to be localtime of creation of xml
|
46
48
|
parsed["timestamp"] = xml.xpath("//RD5WEB").attribute("t").to_s
|
47
49
|
parsed["preheating"] = preheating
|
48
50
|
parsed
|
@@ -58,8 +60,7 @@ module AtreaControl
|
|
58
60
|
"preheat_temperature" => values["preheat_temperature"].to_f / 10.0,
|
59
61
|
"input_temperature" => values["input_temperature"].to_f / 10.0,
|
60
62
|
"preheating" => values["preheating"],
|
61
|
-
"timestamp" =>
|
62
|
-
"valid_for" => Time.now,
|
63
|
+
"timestamp" => Time.strptime(values["timestamp"], "%Y-%m-%d %H:%M:%S"),
|
63
64
|
}
|
64
65
|
end
|
65
66
|
|
data/lib/atrea_control.rb
CHANGED
@@ -7,6 +7,12 @@ require "yaml"
|
|
7
7
|
module AtreaControl
|
8
8
|
class Error < StandardError; end
|
9
9
|
|
10
|
+
class SessionExpired < Error
|
11
|
+
def message
|
12
|
+
"Session expired. Please perform login again."
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
10
16
|
autoload :Duplex, "atrea_control/duplex"
|
11
17
|
autoload :Logger, "atrea_control/logger"
|
12
18
|
autoload :SensorParser, "atrea_control/sensor_parser"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: atrea_control
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.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:
|
11
|
+
date: 2025-01-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: i18n
|
@@ -52,20 +52,6 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '2.1'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: selenium-webdriver
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: 4.25.0
|
62
|
-
type: :runtime
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: 4.25.0
|
69
55
|
description: Read data from web controller of RD5 duplex by Atrea.
|
70
56
|
email:
|
71
57
|
- pokorny@luk4s.cz
|
@@ -119,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
119
105
|
- !ruby/object:Gem::Version
|
120
106
|
version: '0'
|
121
107
|
requirements: []
|
122
|
-
rubygems_version: 3.5.
|
108
|
+
rubygems_version: 3.5.22
|
123
109
|
signing_key:
|
124
110
|
specification_version: 4
|
125
111
|
summary: Get data control.atrea.eu
|