atrea_control 3.2.1 → 4.0.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: 882aba37152d02169b498490ecf172a54dd23d13ce1adbd1942d0352b7657631
4
- data.tar.gz: e9476fea5a2f52ab43daefd238afd31a2e47f48c9ff0e522c2380c0ff020c43c
3
+ metadata.gz: da49b797a6e3e359751ab8ef6b64768d53ddc81b06f91c78dbe868f510540926
4
+ data.tar.gz: 869cddecea901cc565ff961818a0788e45243a9ec337978ebcb2e3e157de6f53
5
5
  SHA512:
6
- metadata.gz: cff2b7d059df5833e7d7caa24c8db787c4ae79b566023923f93bf4d46c70710171c5ed59734364d4c91bff4d1743b98ec2a9dc7f03bd0bb0d3dccf635b9c4f7c
7
- data.tar.gz: 36053dfa7f5a609672cd07408f678b7187f94b88b6e116d7c1c602e229da194766f73b2a5de45d339ff9bf1092081b120427a06322b99c2940b44a46d7afadfd
6
+ metadata.gz: ceba4c6afb798d0f72fb58b087bf65594881894b5d6284b1623122774c14df01ac3904f824c96fc00ff09b57698aa1d8578b33223e8874696c7ea76155955457
7
+ data.tar.gz: 3035973ce25e37db961c3a8aac07c124e75284afce1f8caa7d90b43b60771e359196e65f6496f71a6e8f5888f3419852f8627a7425bc8b665ea2dd26c87ea9f9
@@ -17,3 +17,14 @@ jobs:
17
17
  bundler-cache: true
18
18
  - name: Run tests
19
19
  run: bundle exec rspec
20
+ lint:
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+ - name: Set up Ruby
25
+ uses: ruby/setup-ruby@v1
26
+ with:
27
+ ruby-version: '4'
28
+ bundler-cache: true
29
+ - name: Run RuboCop
30
+ run: bundle exec rubocop
data/.rubocop_todo.yml CHANGED
@@ -18,10 +18,16 @@ Gemspec/RequiredRubyVersion:
18
18
  Metrics/AbcSize:
19
19
  Max: 34
20
20
 
21
+ # Offense count: 1
22
+ # Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns.
23
+ Metrics/ClassLength:
24
+ Exclude:
25
+ - 'lib/atrea_control/duplex/login.rb'
26
+
21
27
  # Offense count: 3
22
28
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
23
29
  Metrics/MethodLength:
24
- Max: 21
30
+ Max: 23
25
31
 
26
32
  # Offense count: 1
27
33
  # Configuration parameters: Prefixes, AllowedPatterns.
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 4.0.2
1
+ 4.0.7
data/AGENTS.md ADDED
@@ -0,0 +1,51 @@
1
+ # Repository guidance
2
+
3
+ ## Commands and toolchain
4
+ - Install dependencies: `bin/setup` (`bundle install`).
5
+ - Full local checks: `bundle exec rake` runs specs, then RuboCop.
6
+ - CI runs the RSpec Ruby matrix and a separate `bundle exec rubocop` job.
7
+ - Focused test: `bundle exec rspec spec/atrea_control/duplex/unit_spec.rb`;
8
+ append `:LINE` to select an example.
9
+ - Ruby versions differ across config: `.ruby-version` pins 4.0.7, gemspec
10
+ allows >= 3.2, RuboCop targets 3.3. Do not infer minimum Ruby from local version.
11
+ - RuboCop inherits `.rubocop_todo.yml`; RSpec message expectations use
12
+ `receive`, not `have_received`.
13
+
14
+ ## Protocol and state
15
+ - This gem wraps Atrea RD5's web portal. `Duplex::Login` obtains tokens;
16
+ `Duplex::Request` performs unit requests; `UserCtrl` discovers sensor/mode
17
+ mappings; `SensorParser` decodes readings and encodes writes.
18
+ - Sensor and mode maps use string keys. Derive sensor IDs from `UserCtrl`;
19
+ fixture IDs are not universal device configuration.
20
+ - `UserCtrl.data` is persisted by `home_control`. Preserve JSON-safe
21
+ `input_temperature_source` metadata when exporting/reconstructing `user_ctrl:`;
22
+ a sensor ID alone cannot represent conditional inlet-temperature selection.
23
+ - RD5 Modbus register semantics inform command policy, not cloud HTTP framing.
24
+ See `docs/rd5-cloud-protocol.md` for supported profiles and evidence limits.
25
+ - `Unit` caches parsed readings; `refresh!` fetches again. `values` raises
26
+ `AtreaControl::SessionExpired` when device timestamp is missing or older
27
+ than 15 minutes, rather than relying on HTTP authentication errors.
28
+ - All current-value readers validate snapshots. Failed refresh stays failed until
29
+ explicit `refresh!`; write attempts discard prewrite data even on failure.
30
+ - `set_power`/`set_mode` verify by default and require caller-proven
31
+ `verification_registers:`; legacy setters are transport-only. Never infer a
32
+ read-back register from PDF addresses or automatically replay timed-out writes.
33
+ - Use Faraday/Net::HTTP: login has a 300-second total limit, HTTP requests 60.
34
+ Standard `Timeout` wrappers use an explicit exception class so Net::HTTP closes
35
+ sockets during TLS setup; do not reintroduce a custom transport or write retries.
36
+ - Loading `atrea_control` registers `config/locales/*.yml` and sets global
37
+ `I18n.default_locale` to `:cs`.
38
+
39
+ ## Tests
40
+ - Specs use WebMock and XML/HTML fixtures in `spec/fixtures/files`;
41
+ normal test runs need no portal credentials or physical unit.
42
+ - Support files are not auto-loaded. Specs using shared `"userCtrl"` context
43
+ explicitly require `spec/support/user_ctrl.rb`.
44
+ - `unit.xml` contains an old timestamp; most Unit specs stub `valid?`.
45
+ Exercise real validity behavior with controlled timestamps.
46
+
47
+ ## Packaging
48
+ - Gem contents come from `git ls-files`, excluding test/spec/features.
49
+ New runtime files must be tracked to enter built gem.
50
+ - `bundle exec rake release` pushes commits/tags and publishes to RubyGems;
51
+ it is not a local verification command.
data/CHANGELOG.md CHANGED
@@ -1,4 +1,66 @@
1
1
  ## [Unreleased]
2
+
3
+ ## [4.0.0] - 2026-10-26
4
+ ### Breaking changes
5
+ - Reject `nil` (formerly liable to become zero), booleans, negative/fractional
6
+ values and malformed setter strings with `ArgumentError`; never truncate or clamp.
7
+ - Validate power domains, discovered modes, equipment prerequisites and schedule
8
+ state. Unsupported or incomplete configuration now fails explicitly.
9
+ - Recheck freshness on all current-value getters and serializers. Failed refresh
10
+ invalidates accessible data until `refresh!`; stale cached values no longer leak.
11
+ - Preserve manual schedule control; scheduled/temporary writes request temporary
12
+ control even for zero power, rather than unconditionally switching policy.
13
+ - Return `nil` for unavailable/unsupported optional inlet temperature, not a
14
+ fabricated zero. Add `required_temperature` reader/hash key while retaining
15
+ historical `preheat_temperature`; both mean requested temperature.
16
+
17
+ ### Change
18
+ - Export JSON-safe `input_temperature_source` in `UserCtrl.data` so persisted
19
+ configuration retains conditional inlet sensor selection. Custom `user_ctrl:`
20
+ objects should expose that metadata; the unreleased `input_temperature_profile`
21
+ accessor is replaced. Sensor-selection rules stay in the gem, not consumer UIs.
22
+ - Include `Sync=1` on the unit-login POST, matching the current portal's
23
+ synchronous handshake. Without it, the session query could stay at SID zero
24
+ despite recent unit communication. Add a regression that requires this flag
25
+ before establishing a session.
26
+ - Parse strict unit/configuration XML and unsigned raw registers; decode signed
27
+ temperatures only at projection. Reject malformed data through library errors.
28
+ - Accept valid device timestamps without leading zeroes, as observed live
29
+ (`17:7:32`), while retaining strict date/time and timezone validation.
30
+ - Publish atomic snapshots, enforce the strict 15-minute age boundary and allow
31
+ at most 60 seconds of future clock skew. Discard snapshots on every write attempt.
32
+ - Add `RD5Configuration`, configuration-derived command/control mappings and exact
33
+ unsigned 16-bit command encoding. Never execute downloaded configuration code.
34
+ - Add optional IANA `time_zone:`; `nil` retains process-local interpretation.
35
+ Invalid zones and ambiguous/nonexistent DST timestamps raise `ProtocolError`.
36
+ - Add `set_power`/`set_mode` with verification enabled by default, a 30-second
37
+ absolute budget and five-second polling. Verification requires caller-supplied,
38
+ independently proven `verification_registers:`; no current cloud read-back
39
+ profile is automatically trusted. Missing mappings fail before writing.
40
+ - Keep assignment setters unconfirmed (`verify: false`); HTTP success alone is
41
+ not application acknowledgement. Verification timeout after dispatch reports
42
+ unknown outcome through `WriteNotConfirmed`, without write retries.
43
+ - Add explicit login unit selection by `ident` (default: first listed unit), a
44
+ five-minute total limit, one-second polling and bounded HTTP requests.
45
+ Distinguish authentication, protocol, transport, timeout and configuration errors.
46
+ - Add `tzinfo ~> 2.0` for explicit IANA/DST handling. Keep Faraday/Net::HTTP as
47
+ the sole HTTP transport, with standard-library total timeouts: login at most
48
+ 300 seconds, each HTTP operation at most 60 seconds. Remove the HTTPX dependency,
49
+ custom transport plugin and socket/resolver machinery. Explicit timeout exception
50
+ classes preserve Net::HTTP TLS cleanup. Automatic retries remain disabled.
51
+ - Verify live RD5 login, configuration, values, getters/JSON, three refreshes and
52
+ expiry/recovery on 2026-10-25 after correcting the handshake. Validate command
53
+ construction against the live configuration without dispatching writes.
54
+ Acknowledgements, live writes and requested-value read-back remain unverified.
55
+ Add an independent RuboCop CI job alongside the Ruby spec matrix.
56
+
57
+ ### Security
58
+ - Remove credential-bearing response/URL/SID diagnostics and executable locale
59
+ regeneration; validate XML without DTD/network resolution. Login diagnostics
60
+ retain stage, status, elapsed time and poll counts without secrets.
61
+ - upgrade ruby 4.0.7
62
+ - upgrade gems
63
+
2
64
  ## [3.2.0] - 2026-04-16
3
65
  ### Security
4
66
  - upgrade gems
@@ -23,7 +85,7 @@
23
85
  - "session" validity check & expiration (exception)
24
86
  ### Changed
25
87
  - ruby version 3.3+
26
- -
88
+
27
89
  ## [2.2.0] - 2024-10-20
28
90
  ### Added
29
91
  - timestamp from atrea server
data/Gemfile CHANGED
@@ -7,10 +7,10 @@ gemspec
7
7
 
8
8
  gem "pry"
9
9
  gem "rake", "~> 13.0"
10
- gem "rspec", "~> 3.10"
11
- gem "rubocop", "~> 1.7", require: false
12
- gem "rubocop-rspec", "~> 3.1", require: false
10
+ gem "rspec", "~> 3.13"
11
+ gem "rubocop", "~> 1.88", require: false
12
+ gem "rubocop-rspec", "~> 3.10", require: false
13
13
  group :test do
14
14
  gem "simplecov", require: false
15
- gem "webmock", "~> 3.14"
15
+ gem "webmock", "~> 3.26"
16
16
  end
data/Gemfile.lock CHANGED
@@ -1,11 +1,12 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- atrea_control (3.2.1)
5
- faraday (~> 2.7)
4
+ atrea_control (4.0.0)
5
+ faraday (~> 2.14)
6
6
  faraday-cookie_jar (~> 0.0)
7
- i18n (~> 1.14)
8
- nokogiri (~> 1.15)
7
+ i18n (~> 1.15)
8
+ nokogiri (~> 1.16)
9
+ tzinfo (~> 2.0)
9
10
 
10
11
  GEM
11
12
  remote: https://rubygems.org/
@@ -13,49 +14,51 @@ GEM
13
14
  addressable (2.9.0)
14
15
  public_suffix (>= 2.0.2, < 8.0)
15
16
  ast (2.4.3)
16
- bigdecimal (4.1.1)
17
+ bigdecimal (4.1.3)
17
18
  coderay (1.1.3)
18
- concurrent-ruby (1.3.6)
19
+ concurrent-ruby (1.3.8)
19
20
  crack (1.0.1)
20
21
  bigdecimal
21
22
  rexml
22
23
  diff-lcs (1.6.2)
23
- docile (1.4.1)
24
- domain_name (0.6.20240107)
25
- faraday (2.14.1)
26
- faraday-net_http (>= 2.0, < 3.5)
24
+ domain_name (0.7.20261007)
25
+ faraday (2.15.0)
26
+ faraday-net_http (>= 2.0, < 3.6)
27
27
  json
28
28
  logger
29
29
  faraday-cookie_jar (0.0.8)
30
30
  faraday (>= 0.8.0)
31
31
  http-cookie (>= 1.0.0)
32
- faraday-net_http (3.4.2)
32
+ faraday-net_http (3.5.0)
33
33
  net-http (~> 0.5)
34
34
  hashdiff (1.2.1)
35
- http-cookie (1.1.4)
35
+ http-cookie (1.1.6)
36
36
  domain_name (~> 0.5)
37
- i18n (1.14.8)
37
+ i18n (1.15.2)
38
38
  concurrent-ruby (~> 1.0)
39
- io-console (0.8.2)
40
- json (2.19.3)
41
- language_server-protocol (3.17.0.5)
39
+ io-console (0.9.4)
40
+ json (3.1.0)
41
+ language_server-protocol (3.17.0.6)
42
42
  lint_roller (1.1.0)
43
43
  logger (1.7.0)
44
44
  method_source (1.1.0)
45
- net-http (0.9.1)
45
+ net-http (0.10.0)
46
+ net-protocol (>= 0.3.0)
46
47
  uri (>= 0.11.1)
47
- nokogiri (1.19.2-arm64-darwin)
48
+ net-protocol (0.4.0)
49
+ timeout
50
+ nokogiri (1.19.4-arm64-darwin)
48
51
  racc (~> 1.4)
49
- nokogiri (1.19.2-x86_64-darwin)
52
+ nokogiri (1.19.4-x86_64-darwin)
50
53
  racc (~> 1.4)
51
- nokogiri (1.19.2-x86_64-linux-gnu)
54
+ nokogiri (1.19.4-x86_64-linux-gnu)
52
55
  racc (~> 1.4)
53
- parallel (2.0.1)
54
- parser (3.3.11.1)
56
+ parallel (2.3.0)
57
+ parser (3.3.13.0)
55
58
  ast (~> 2.4.1)
56
59
  racc
57
60
  prism (1.9.0)
58
- pry (0.16.0)
61
+ pry (0.16.1)
59
62
  coderay (~> 1.1)
60
63
  method_source (~> 1.0)
61
64
  reline (>= 0.6.0)
@@ -63,8 +66,8 @@ GEM
63
66
  racc (1.8.1)
64
67
  rainbow (3.1.1)
65
68
  rake (13.4.2)
66
- regexp_parser (2.12.0)
67
- reline (0.6.3)
69
+ regexp_parser (2.13.1)
70
+ reline (0.7.0)
68
71
  io-console (~> 0.5)
69
72
  rexml (3.4.4)
70
73
  rspec (3.13.2)
@@ -80,35 +83,34 @@ GEM
80
83
  diff-lcs (>= 1.2.0, < 2.0)
81
84
  rspec-support (~> 3.13.0)
82
85
  rspec-support (3.13.7)
83
- rubocop (1.86.1)
84
- json (~> 2.3)
86
+ rubocop (1.92.1)
87
+ json (>= 2.3)
85
88
  language_server-protocol (~> 3.17.0.2)
86
89
  lint_roller (~> 1.1.0)
87
90
  parallel (>= 1.10)
88
91
  parser (>= 3.3.0.2)
89
92
  rainbow (>= 2.2.2, < 4.0)
90
- regexp_parser (>= 2.9.3, < 3.0)
93
+ regexp_parser (>= 2.11.3, < 3.0)
91
94
  rubocop-ast (>= 1.49.0, < 2.0)
92
95
  ruby-progressbar (~> 1.7)
93
96
  unicode-display_width (>= 2.4.0, < 4.0)
94
- rubocop-ast (1.49.1)
97
+ rubocop-ast (1.50.0)
95
98
  parser (>= 3.3.7.2)
96
99
  prism (~> 1.7)
97
- rubocop-rspec (3.9.0)
100
+ rubocop-rspec (3.10.2)
98
101
  lint_roller (~> 1.1)
99
- rubocop (~> 1.81)
102
+ regexp_parser (>= 2.0)
103
+ rubocop (~> 1.86, >= 1.86.2)
100
104
  ruby-progressbar (1.13.0)
101
- simplecov (0.22.0)
102
- docile (~> 1.1)
103
- simplecov-html (~> 0.11)
104
- simplecov_json_formatter (~> 0.1)
105
- simplecov-html (0.13.2)
106
- simplecov_json_formatter (0.1.4)
107
- unicode-display_width (3.2.0)
108
- unicode-emoji (~> 4.1)
109
- unicode-emoji (4.2.0)
110
- uri (1.1.1)
111
- webmock (3.26.2)
105
+ simplecov (1.3.2)
106
+ timeout (0.6.1)
107
+ tzinfo (2.0.6)
108
+ concurrent-ruby (~> 1.0)
109
+ unicode-display_width (3.3.0)
110
+ unicode-emoji (~> 4.3)
111
+ unicode-emoji (4.3.0)
112
+ uri (1.1.2)
113
+ webmock (3.34.0)
112
114
  addressable (>= 2.8.0)
113
115
  crack (>= 0.3.2)
114
116
  hashdiff (>= 0.4.0, < 2.0.0)
@@ -125,11 +127,11 @@ DEPENDENCIES
125
127
  atrea_control!
126
128
  pry
127
129
  rake (~> 13.0)
128
- rspec (~> 3.10)
129
- rubocop (~> 1.7)
130
- rubocop-rspec (~> 3.1)
130
+ rspec (~> 3.13)
131
+ rubocop (~> 1.88)
132
+ rubocop-rspec (~> 3.10)
131
133
  simplecov
132
- webmock (~> 3.14)
134
+ webmock (~> 3.26)
133
135
 
134
136
  BUNDLED WITH
135
- 4.0.10
137
+ 4.0.20