alpha-hwr 0.2.0__tar.gz

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.
Files changed (146) hide show
  1. alpha_hwr-0.2.0/.bumpversion.cfg +27 -0
  2. alpha_hwr-0.2.0/CHANGELOG.md +63 -0
  3. alpha_hwr-0.2.0/CONTRIBUTING.md +143 -0
  4. alpha_hwr-0.2.0/LICENSE +21 -0
  5. alpha_hwr-0.2.0/MANIFEST.in +21 -0
  6. alpha_hwr-0.2.0/PKG-INFO +419 -0
  7. alpha_hwr-0.2.0/README.md +372 -0
  8. alpha_hwr-0.2.0/docs/TESTING_STRATEGY.md +580 -0
  9. alpha_hwr-0.2.0/docs/api/client.md +109 -0
  10. alpha_hwr-0.2.0/docs/api/constants.md +95 -0
  11. alpha_hwr-0.2.0/docs/api/models.md +375 -0
  12. alpha_hwr-0.2.0/docs/getting_started/installation.md +76 -0
  13. alpha_hwr-0.2.0/docs/getting_started/quick_start.md +280 -0
  14. alpha_hwr-0.2.0/docs/guides/backup_restore.md +383 -0
  15. alpha_hwr-0.2.0/docs/guides/cli_guide.md +860 -0
  16. alpha_hwr-0.2.0/docs/guides/control_modes.md +335 -0
  17. alpha_hwr-0.2.0/docs/guides/historical_data.md +120 -0
  18. alpha_hwr-0.2.0/docs/guides/time_management.md +91 -0
  19. alpha_hwr-0.2.0/docs/guides/understanding_telemetry.md +424 -0
  20. alpha_hwr-0.2.0/docs/index.md +12 -0
  21. alpha_hwr-0.2.0/docs/integrations/esphome.md +369 -0
  22. alpha_hwr-0.2.0/docs/protocol/architecture.md +117 -0
  23. alpha_hwr-0.2.0/docs/protocol/autoadapt_modes.md +225 -0
  24. alpha_hwr-0.2.0/docs/protocol/ble_architecture.md +464 -0
  25. alpha_hwr-0.2.0/docs/protocol/connection.md +72 -0
  26. alpha_hwr-0.2.0/docs/protocol/control.md +215 -0
  27. alpha_hwr-0.2.0/docs/protocol/control_modes.md +372 -0
  28. alpha_hwr-0.2.0/docs/protocol/device_info.md +113 -0
  29. alpha_hwr-0.2.0/docs/protocol/energy_power.md +124 -0
  30. alpha_hwr-0.2.0/docs/protocol/packet_traces/01_connection.md +577 -0
  31. alpha_hwr-0.2.0/docs/protocol/packet_traces/02_authentication.md +395 -0
  32. alpha_hwr-0.2.0/docs/protocol/packet_traces/03_telemetry_stream.md +133 -0
  33. alpha_hwr-0.2.0/docs/protocol/packet_traces/04_set_mode.md +118 -0
  34. alpha_hwr-0.2.0/docs/protocol/packet_traces/05_schedule_write.md +136 -0
  35. alpha_hwr-0.2.0/docs/protocol/schedules.md +682 -0
  36. alpha_hwr-0.2.0/docs/protocol/telemetry.md +104 -0
  37. alpha_hwr-0.2.0/docs/protocol/wire_format.md +96 -0
  38. alpha_hwr-0.2.0/docs/reference/data_models.md +233 -0
  39. alpha_hwr-0.2.0/docs/reference/hardware.md +66 -0
  40. alpha_hwr-0.2.0/docs/reimplementation/README.md +283 -0
  41. alpha_hwr-0.2.0/docs/reimplementation/architecture.md +334 -0
  42. alpha_hwr-0.2.0/docs/reimplementation/checklist.md +307 -0
  43. alpha_hwr-0.2.0/docs/reimplementation/common_pitfalls.md +919 -0
  44. alpha_hwr-0.2.0/docs/reimplementation/layer_by_layer.md +863 -0
  45. alpha_hwr-0.2.0/docs/reimplementation/test_vectors.md +583 -0
  46. alpha_hwr-0.2.0/mkdocs.yml +101 -0
  47. alpha_hwr-0.2.0/pyproject.toml +94 -0
  48. alpha_hwr-0.2.0/setup.cfg +4 -0
  49. alpha_hwr-0.2.0/src/alpha_hwr/__init__.py +51 -0
  50. alpha_hwr-0.2.0/src/alpha_hwr/cli/__init__.py +9 -0
  51. alpha_hwr-0.2.0/src/alpha_hwr/cli/app.py +82 -0
  52. alpha_hwr-0.2.0/src/alpha_hwr/cli/commands/__init__.py +5 -0
  53. alpha_hwr-0.2.0/src/alpha_hwr/cli/commands/clock.py +197 -0
  54. alpha_hwr-0.2.0/src/alpha_hwr/cli/commands/config.py +204 -0
  55. alpha_hwr-0.2.0/src/alpha_hwr/cli/commands/control.py +461 -0
  56. alpha_hwr-0.2.0/src/alpha_hwr/cli/commands/device.py +189 -0
  57. alpha_hwr-0.2.0/src/alpha_hwr/cli/commands/events.py +374 -0
  58. alpha_hwr-0.2.0/src/alpha_hwr/cli/commands/history.py +277 -0
  59. alpha_hwr-0.2.0/src/alpha_hwr/cli/commands/monitor.py +140 -0
  60. alpha_hwr-0.2.0/src/alpha_hwr/cli/commands/schedule.py +345 -0
  61. alpha_hwr-0.2.0/src/alpha_hwr/cli/common.py +133 -0
  62. alpha_hwr-0.2.0/src/alpha_hwr/cli/output/__init__.py +35 -0
  63. alpha_hwr-0.2.0/src/alpha_hwr/cli/output/formatters.py +381 -0
  64. alpha_hwr-0.2.0/src/alpha_hwr/cli/output/themes.py +37 -0
  65. alpha_hwr-0.2.0/src/alpha_hwr/client.py +693 -0
  66. alpha_hwr-0.2.0/src/alpha_hwr/command_processor.py +227 -0
  67. alpha_hwr-0.2.0/src/alpha_hwr/config.py +65 -0
  68. alpha_hwr-0.2.0/src/alpha_hwr/constants.py +602 -0
  69. alpha_hwr-0.2.0/src/alpha_hwr/core/__init__.py +16 -0
  70. alpha_hwr-0.2.0/src/alpha_hwr/core/authentication.py +446 -0
  71. alpha_hwr-0.2.0/src/alpha_hwr/core/session.py +364 -0
  72. alpha_hwr-0.2.0/src/alpha_hwr/core/transport.py +698 -0
  73. alpha_hwr-0.2.0/src/alpha_hwr/event_log.py +165 -0
  74. alpha_hwr-0.2.0/src/alpha_hwr/exceptions.py +22 -0
  75. alpha_hwr-0.2.0/src/alpha_hwr/models.py +782 -0
  76. alpha_hwr-0.2.0/src/alpha_hwr/profile_parser.py +226 -0
  77. alpha_hwr-0.2.0/src/alpha_hwr/protocol/__init__.py +31 -0
  78. alpha_hwr-0.2.0/src/alpha_hwr/protocol/codec.py +361 -0
  79. alpha_hwr-0.2.0/src/alpha_hwr/protocol/frame_builder.py +651 -0
  80. alpha_hwr-0.2.0/src/alpha_hwr/protocol/frame_parser.py +442 -0
  81. alpha_hwr-0.2.0/src/alpha_hwr/protocol/telemetry_decoder.py +768 -0
  82. alpha_hwr-0.2.0/src/alpha_hwr/services/__init__.py +38 -0
  83. alpha_hwr-0.2.0/src/alpha_hwr/services/base.py +214 -0
  84. alpha_hwr-0.2.0/src/alpha_hwr/services/configuration.py +641 -0
  85. alpha_hwr-0.2.0/src/alpha_hwr/services/control.py +1048 -0
  86. alpha_hwr-0.2.0/src/alpha_hwr/services/device_info.py +438 -0
  87. alpha_hwr-0.2.0/src/alpha_hwr/services/event_log.py +346 -0
  88. alpha_hwr-0.2.0/src/alpha_hwr/services/history.py +454 -0
  89. alpha_hwr-0.2.0/src/alpha_hwr/services/schedule.py +928 -0
  90. alpha_hwr-0.2.0/src/alpha_hwr/services/telemetry.py +462 -0
  91. alpha_hwr-0.2.0/src/alpha_hwr/services/time.py +385 -0
  92. alpha_hwr-0.2.0/src/alpha_hwr/utils.py +60 -0
  93. alpha_hwr-0.2.0/src/alpha_hwr.egg-info/PKG-INFO +419 -0
  94. alpha_hwr-0.2.0/src/alpha_hwr.egg-info/SOURCES.txt +144 -0
  95. alpha_hwr-0.2.0/src/alpha_hwr.egg-info/dependency_links.txt +1 -0
  96. alpha_hwr-0.2.0/src/alpha_hwr.egg-info/entry_points.txt +2 -0
  97. alpha_hwr-0.2.0/src/alpha_hwr.egg-info/requires.txt +20 -0
  98. alpha_hwr-0.2.0/src/alpha_hwr.egg-info/top_level.txt +1 -0
  99. alpha_hwr-0.2.0/tests/benchmarks/test_performance.py +258 -0
  100. alpha_hwr-0.2.0/tests/conftest.py +151 -0
  101. alpha_hwr-0.2.0/tests/integration/test_client_workflows.py +368 -0
  102. alpha_hwr-0.2.0/tests/mocks/__init__.py +5 -0
  103. alpha_hwr-0.2.0/tests/mocks/mock_pump.py +700 -0
  104. alpha_hwr-0.2.0/tests/mocks/mock_transport.py +294 -0
  105. alpha_hwr-0.2.0/tests/reference/test_protocol_vectors.py +361 -0
  106. alpha_hwr-0.2.0/tests/test_active_control.py +106 -0
  107. alpha_hwr-0.2.0/tests/test_advanced_telemetry.py +112 -0
  108. alpha_hwr-0.2.0/tests/test_autoadapt_modes.py +120 -0
  109. alpha_hwr-0.2.0/tests/test_backup_restore.py +346 -0
  110. alpha_hwr-0.2.0/tests/test_basic.py +15 -0
  111. alpha_hwr-0.2.0/tests/test_client_telemetry.py +225 -0
  112. alpha_hwr-0.2.0/tests/test_clock.py +85 -0
  113. alpha_hwr-0.2.0/tests/test_command_processor.py +37 -0
  114. alpha_hwr-0.2.0/tests/test_config.py +38 -0
  115. alpha_hwr-0.2.0/tests/test_configuration_service.py +364 -0
  116. alpha_hwr-0.2.0/tests/test_control_mode_retrieval.py +138 -0
  117. alpha_hwr-0.2.0/tests/test_control_parsing.py +178 -0
  118. alpha_hwr-0.2.0/tests/test_control_service_extended.py +402 -0
  119. alpha_hwr-0.2.0/tests/test_device_info.py +144 -0
  120. alpha_hwr-0.2.0/tests/test_full_backup_restore_cycle.py +208 -0
  121. alpha_hwr-0.2.0/tests/test_history_parsing.py +255 -0
  122. alpha_hwr-0.2.0/tests/test_history_service.py +366 -0
  123. alpha_hwr-0.2.0/tests/test_mock_pump.py +176 -0
  124. alpha_hwr-0.2.0/tests/test_models.py +55 -0
  125. alpha_hwr-0.2.0/tests/test_packet_creation.py +327 -0
  126. alpha_hwr-0.2.0/tests/test_packet_structure.py +138 -0
  127. alpha_hwr-0.2.0/tests/test_profile_parser.py +91 -0
  128. alpha_hwr-0.2.0/tests/test_protocol_expanded.py +78 -0
  129. alpha_hwr-0.2.0/tests/test_schedule_coverage.py +72 -0
  130. alpha_hwr-0.2.0/tests/test_schedule_entry.py +639 -0
  131. alpha_hwr-0.2.0/tests/test_schedule_protocol.py +322 -0
  132. alpha_hwr-0.2.0/tests/test_schedule_service.py +662 -0
  133. alpha_hwr-0.2.0/tests/test_schedule_write.py +516 -0
  134. alpha_hwr-0.2.0/tests/test_telemetry_integration.py +332 -0
  135. alpha_hwr-0.2.0/tests/test_telemetry_service.py +616 -0
  136. alpha_hwr-0.2.0/tests/test_utils.py +22 -0
  137. alpha_hwr-0.2.0/tests/test_wire_protocol.py +146 -0
  138. alpha_hwr-0.2.0/tests/unit/core/test_base_service.py +172 -0
  139. alpha_hwr-0.2.0/tests/unit/core/test_control_service.py +114 -0
  140. alpha_hwr-0.2.0/tests/unit/core/test_device_info_service.py +124 -0
  141. alpha_hwr-0.2.0/tests/unit/core/test_event_log_service.py +98 -0
  142. alpha_hwr-0.2.0/tests/unit/core/test_time_service.py +144 -0
  143. alpha_hwr-0.2.0/tests/unit/protocol/test_codec.py +296 -0
  144. alpha_hwr-0.2.0/tests/unit/protocol/test_frame_builder.py +417 -0
  145. alpha_hwr-0.2.0/tests/unit/protocol/test_frame_parser.py +332 -0
  146. alpha_hwr-0.2.0/tests/unit/protocol/test_telemetry_decoder.py +515 -0
@@ -0,0 +1,27 @@
1
+ [bumpversion]
2
+ current_version = 0.2.0
3
+ commit = True
4
+ tag = True
5
+ tag_name = v{new_version}
6
+ tag_message = Release version {new_version}
7
+ message = Bump version: {current_version} → {new_version}
8
+
9
+ [bumpversion:file:pyproject.toml]
10
+ search = version = "{current_version}"
11
+ replace = version = "{new_version}"
12
+
13
+ [bumpversion:file:src/alpha_hwr/__init__.py]
14
+ search = __version__ = "{current_version}"
15
+ replace = __version__ = "{new_version}"
16
+
17
+ [bumpversion:file:CHANGELOG.md]
18
+ search = ## [Unreleased]
19
+ replace = ## [Unreleased]
20
+
21
+ [bumpversion:file:mkdocs.yml]
22
+ search = version: "{current_version}"
23
+ replace = version: "{new_version}"
24
+
25
+ [bumpversion:file:docs/index.md]
26
+ search = *Version: {current_version}*
27
+ replace = *Version: {new_version}*
@@ -0,0 +1,63 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [## [Unreleased]] - 2026-02-01
11
+
12
+ ### Added
13
+
14
+ - **BLE connection to Grundfos ALPHA HWR pumps**
15
+ - **Telemetry reading** (Flow, Head, Power, Temperature, Voltage/Current, Speed)
16
+ - **Passive monitoring mode** with continuous data stream
17
+ - **CLI interface** for monitoring and control
18
+ - **AsyncIO-based architecture** using `bleak`
19
+ - **Type-safe API** with Pydantic models
20
+ - **Cross-platform device addressing** (macOS UUID / Linux+Windows MAC)
21
+
22
+ #### Service Enhancements
23
+
24
+ - **Power-On Time History**
25
+ - Added power-on time trend data to HistoryService (Object 53, SubID 454)
26
+ - Extended TrendDataCollection model with `power_on_time_series` field
27
+ - Updated history CLI to display power-on time trends in hours
28
+ - **Event Log Service - Complete Protocol Decoding**
29
+ - Fully decoded EventLogMetadata structure (SubID 10199, 7 bytes)
30
+ - CLI commands: `alpha-hwr events list`, `alpha-hwr events show INDEX`, `alpha-hwr events metadata`
31
+ - **History Service - CLI Implementation**
32
+ - New CLI commands for historical/trend data access
33
+ - `alpha-hwr history trends [--detailed]` - Display flow/head/temperature trends
34
+ - `alpha-hwr history timestamps [--count 10|100]` - Show cycle timestamps
35
+ - **Schedule Management**
36
+ - Read/write weekly schedules from all 5 layers (SubIDs 1000-1004)
37
+ - Enable/disable global schedule with `set_schedule_enabled()`
38
+ - CLI commands: `alpha-hwr schedule [--enable|--disable|--set-entry|--clear-day|--clear-layer]`
39
+ - Export/import schedules as JSON for backup/restore
40
+ - **Configuration Backup and Restore**
41
+ - Save/Restore pump configuration including schedules, modes, and setpoints to JSON
42
+ - CLI commands: `alpha-hwr config backup` and `alpha-hwr config restore`
43
+
44
+ ### Changed
45
+
46
+ - **Major Architectural Refactor**
47
+ - **Complete codebase restructure**: Moved from a monolithic client to a modular service-oriented architecture.
48
+ - **New `core` layer**: Handles connection, authentication, session state, and transport independently.
49
+ - **New `protocol` layer**: Separated frame building, parsing, and codec logic. Added support for Class 3 and Class 10 GENI protocols.
50
+ - **New `services` layer**: Logic split into dedicated services (Telemetry, Control, Schedule, etc.).
51
+ - **New `client` facade**: `AlphaHWRClient` delegates to specialized services.
52
+ - **New `cli` structure**: CLI commands organized by domain using Typer.
53
+ - **Control Service - Enhanced Safety and Reliability**
54
+ - Added setpoint validation to all control mode setters
55
+ - Improved error messages for out-of-range setpoints
56
+ - Now uses `transport.query()` for reliable request/response transactions
57
+
58
+ ### Fixed
59
+
60
+ - **Device Statistics Bug**: Fixed statistics returning None after BaseService refactoring.
61
+ - **Schedule Write Operations**: Fixed to use correct OpSpec 0xB3 format discovered through protocol analysis.
62
+ - **BLE Packet Splitting**: Fixed packet splitting logic to handle 3+ chunks for large data writes.
63
+ - **Control Mode Reading**: Fixed incorrect byte offset in `get_control_mode()`.
@@ -0,0 +1,143 @@
1
+ # Contributing to alpha-hwr
2
+
3
+ Thank you for your interest in contributing to alpha-hwr!
4
+
5
+ ## Development Setup
6
+
7
+ 1. **Clone the repository:**
8
+ ```bash
9
+ git clone https://github.com/eman/alpha-hwr.git
10
+ cd alpha-hwr
11
+ ```
12
+
13
+ 2. **Create a virtual environment and install dependencies:**
14
+ ```bash
15
+ python -m venv .venv
16
+ source .venv/bin/activate # On Windows: .venv\Scripts\activate
17
+ pip install -e ".[dev,docs]"
18
+ ```
19
+
20
+ ## Running Tests Locally
21
+
22
+ We provide a convenient script to run all checks that will be executed in CI:
23
+
24
+ ```bash
25
+ ./scripts/check.sh
26
+ ```
27
+
28
+ This will run:
29
+ - Ruff format check
30
+ - Ruff lint
31
+ - MyPy type checking
32
+ - BasedPyright type checking
33
+ - Pytest with coverage
34
+
35
+ ### Running Individual Checks
36
+
37
+ ```bash
38
+ # Format code
39
+ ruff format .
40
+
41
+ # Check formatting
42
+ ruff format --check .
43
+
44
+ # Lint
45
+ ruff check .
46
+
47
+ # Type check with MyPy
48
+ mypy src/alpha_hwr
49
+
50
+ # Type check with BasedPyright
51
+ basedpyright
52
+
53
+ # Run tests
54
+ pytest tests/ -v
55
+
56
+ # Run tests with coverage
57
+ pytest tests/ --cov=alpha_hwr --cov-report=term
58
+
59
+ # Run all checks with tox
60
+ tox
61
+ ```
62
+
63
+ ## Code Quality
64
+
65
+ - **Linting**: Code must pass `ruff check`
66
+ - **Type Checking**: Code must pass `mypy` and `basedpyright`
67
+ - **Testing**: All tests must pass (`pytest`)
68
+ - **Coverage**: Maintain or improve test coverage
69
+
70
+ ## Code Style
71
+
72
+ - We use **Ruff** for formatting and linting
73
+ - Line length: 80 characters
74
+ - Follow PEP 8 conventions
75
+ - Use type hints for all functions
76
+ - Write docstrings for public APIs (Google-style format)
77
+
78
+ ## Architecture
79
+
80
+ Please read `copilot-instructions.md` for architecture guidelines. The project follows a strict layered architecture:
81
+
82
+ - **Core**: Connection, authentication, transport (`src/alpha_hwr/core/`)
83
+ - **Protocol**: Frame building, parsing, codec (`src/alpha_hwr/protocol/`)
84
+ - **Services**: Business logic for Telemetry, Control, Schedule, etc. (`src/alpha_hwr/services/`)
85
+ - **Client**: Unified facade API (`src/alpha_hwr/client.py`)
86
+
87
+ ## Documentation Requirements
88
+
89
+ **IMPORTANT**: When adding or modifying features, you MUST update the corresponding documentation files:
90
+
91
+ 1. **Source Code Documentation**:
92
+ - Add/update docstrings in the source code
93
+ - Follow Google-style docstring format
94
+ - Include parameter types, return types, and examples
95
+
96
+ 2. **User-Facing Documentation** (update ALL applicable files):
97
+ - `README.md` - User-facing examples and CLI usage
98
+ - `CHANGELOG.md` - Add entry under "Unreleased" section
99
+ - `docs/api/client.md` - API method documentation
100
+ - `docs/api/models.md` - Data model documentation
101
+ - `docs/api/constants.md` - Constants and enums
102
+ - `docs/getting_started/quick_start.md` - Usage examples
103
+ - `docs/index.md` - Feature list and overview
104
+ - `docs/protocol/control.md` - Protocol details
105
+ - `docs/reference/data_models.md` - Reference material
106
+
107
+ 3. **What to Document**:
108
+ - New API methods or parameters
109
+ - New control modes or capabilities
110
+ - Protocol changes or discoveries
111
+ - CLI command additions or changes
112
+
113
+ ## Testing
114
+
115
+ - **Unit Tests**: Test protocol logic in isolation (`tests/unit/`)
116
+ - **Integration Tests**: Test end-to-end workflows using MockPump (`tests/integration/`)
117
+ - **Reference Tests**: Validate against known byte-level vectors (`tests/reference/`)
118
+
119
+ All new features should include appropriate tests.
120
+
121
+ ## Submitting Changes
122
+
123
+ 1. Fork the repository
124
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
125
+ 3. Make your changes
126
+ 4. Run `./scripts/check.sh` to ensure all checks pass
127
+ 5. Update relevant documentation
128
+ 6. Commit your changes (`git commit -m 'Add amazing feature'`)
129
+ 7. Push to your fork (`git push origin feature/amazing-feature`)
130
+ 8. Open a Pull Request
131
+
132
+ ## Release Process
133
+
134
+ Releases are managed by maintainers:
135
+
136
+ 1. Update CHANGELOG.md
137
+ 2. Run `bump2version [major|minor|patch]` to create version tag
138
+ 3. Push tags: `git push --tags`
139
+ 4. Create a GitHub Release - this triggers PyPI publishing automatically
140
+
141
+ ## Questions?
142
+
143
+ Open an issue for questions, bug reports, or feature requests.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Emmanuel Levijarvi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,21 @@
1
+ include README.md
2
+ include LICENSE
3
+ include CHANGELOG.md
4
+ include CONTRIBUTING.md
5
+ include pyproject.toml
6
+ include .bumpversion.cfg
7
+ recursive-include src *.py
8
+ recursive-include tests *.py
9
+ recursive-include docs *.md *.yml
10
+ include mkdocs.yml
11
+ exclude .env
12
+ exclude .env.*
13
+ prune .git
14
+ prune .github
15
+ prune .venv
16
+ prune __pycache__
17
+ prune *.egg-info
18
+ prune build
19
+ prune dist
20
+ global-exclude *.pyc
21
+ global-exclude .DS_Store
@@ -0,0 +1,419 @@
1
+ Metadata-Version: 2.4
2
+ Name: alpha-hwr
3
+ Version: 0.2.0
4
+ Summary: Modern Python library and CLI for Grundfos ALPHA HWR pumps via Bluetooth Low Energy
5
+ Author-email: Grundfos Firmware Team <firmware@grundfos.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/eman/alpha-hwr
8
+ Project-URL: Documentation, https://eman.github.io/alpha-hwr
9
+ Project-URL: Repository, https://github.com/eman/alpha-hwr
10
+ Project-URL: Issues, https://github.com/eman/alpha-hwr/issues
11
+ Project-URL: Changelog, https://github.com/eman/alpha-hwr/blob/main/CHANGELOG.md
12
+ Keywords: grundfos,alpha-hwr,pump,ble,bluetooth,iot,hardware,automation
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: System Administrators
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Topic :: System :: Hardware :: Hardware Drivers
21
+ Classifier: Topic :: Home Automation
22
+ Classifier: Topic :: System :: Monitoring
23
+ Classifier: Framework :: AsyncIO
24
+ Classifier: Operating System :: OS Independent
25
+ Requires-Python: >=3.13
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Requires-Dist: bleak>=0.19.0
29
+ Requires-Dist: pydantic>=2.0.0
30
+ Requires-Dist: pydantic-settings>=2.0.0
31
+ Requires-Dist: typer>=0.9.0
32
+ Requires-Dist: rich>=13.0.0
33
+ Provides-Extra: dev
34
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
35
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
36
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
37
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
38
+ Requires-Dist: pytest-benchmark>=4.0.0; extra == "dev"
39
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
40
+ Requires-Dist: tox>=4.0.0; extra == "dev"
41
+ Requires-Dist: bump2version>=1.0.0; extra == "dev"
42
+ Requires-Dist: basedpyright>=1.0.0; extra == "dev"
43
+ Provides-Extra: docs
44
+ Requires-Dist: mkdocs-material; extra == "docs"
45
+ Requires-Dist: mkdocstrings[python]; extra == "docs"
46
+ Dynamic: license-file
47
+
48
+ # Grundfos ALPHA HWR Python Client
49
+
50
+ A modern Python library and CLI for interacting with Grundfos ALPHA HWR pumps via Bluetooth Low Energy (BLE).
51
+
52
+ ## Features
53
+
54
+ - **Passive Monitoring**: Continuously monitor pump telemetry (Flow, Head, Power, Temperature, Voltage/Current, Speed).
55
+ - **Status Reading**: Read current control mode, setpoint values (with min/max limits), alarms/warnings, cumulative statistics, and device information.
56
+ - **Active Control**: Set pump modes and setpoints with automatic validation (Constant Pressure, Proportional Pressure, Constant Speed, Constant Flow, AutoAdapt variants).
57
+ - **Schedule Management**: Read and write weekly schedules across 5 independent layers with comprehensive validation.
58
+ - **Type-Safe**: Fully typed API using standard Python type hints and Pydantic models.
59
+ - **AsyncIO**: Built on `bleak` for efficient asynchronous BLE communication.
60
+ - **CLI**: Built-in command-line interface for quick diagnostics and control.
61
+
62
+ ## Installation
63
+
64
+ ```bash
65
+ pip install .
66
+ ```
67
+
68
+ ## Configuration
69
+
70
+ The library supports cross-platform device addressing and automatic discovery. Create a `.env` file in your project root:
71
+
72
+ ```bash
73
+ # BLE Device Address
74
+ # Format is platform-specific:
75
+ # - macOS: Uses UUID format (e.g., "A1B2C3D4-E5F6-7890-1234-567890ABCDEF")
76
+ # - Linux/Windows: Uses MAC address format (e.g., "00:11:22:33:44:55")
77
+ #
78
+ # Seamless Cross-Platform: You can provide a comma-separated list of addresses.
79
+ # The library automatically picks the correct one for your current OS.
80
+ ALPHA_HWR_DEVICE_ADDRESS="A1B2C3D4-E5F6-7890-1234-567890ABCDEF, 00:11:22:33:44:55"
81
+ ```
82
+
83
+ ### Automatic Discovery
84
+
85
+ If you don't provide a device address (either via `.env` or as a parameter), the library will automatically attempt to discover and connect to any nearby ALPHA HWR pump.
86
+
87
+ ## Usage
88
+
89
+ ### CLI
90
+
91
+ **Discovery:**
92
+ ```bash
93
+ # Scan for nearby pumps
94
+ alpha-hwr device scan
95
+ ```
96
+
97
+ **Monitoring:**
98
+ ```bash
99
+ # Monitor default device
100
+ alpha-hwr monitor
101
+ ```
102
+
103
+ **Device Information:**
104
+ ```bash
105
+ # Get device information
106
+ alpha-hwr device info
107
+
108
+ # Get cumulative statistics (operating hours, start count)
109
+ alpha-hwr device stats
110
+
111
+ # Check for active alarms and warnings
112
+ alpha-hwr device alarms
113
+ ```
114
+
115
+ **Control Commands:**
116
+ ```bash
117
+ # Show current control mode and setpoint
118
+ alpha-hwr control status
119
+
120
+ # Start/stop pump
121
+ alpha-hwr control start
122
+ alpha-hwr control stop
123
+
124
+ # Set constant pressure mode (meters of water column)
125
+ alpha-hwr control set-pressure 1.5
126
+
127
+ # Set constant speed mode (RPM)
128
+ alpha-hwr control set-speed 2500
129
+ ```
130
+
131
+ **History & Events:**
132
+ ```bash
133
+ # Show historical trend data (last 10 cycles)
134
+ alpha-hwr history trends
135
+
136
+ # Show full 100-cycle history
137
+ alpha-hwr history trends --detailed
138
+
139
+ # List pump event log
140
+ alpha-hwr events list
141
+ ```
142
+
143
+ **Schedule Management:**
144
+ ```bash
145
+ # Read current schedule
146
+ alpha-hwr schedule list
147
+
148
+ # Enable/disable the schedule
149
+ alpha-hwr schedule enable
150
+ alpha-hwr schedule disable
151
+ ```
152
+
153
+ **Configuration Backup & Restore:**
154
+ ```bash
155
+ # Backup pump configuration (schedules, modes, setpoints)
156
+ alpha-hwr config backup pump_config.json
157
+
158
+ # Restore configuration from backup
159
+ alpha-hwr config restore pump_config.json
160
+ ```
161
+
162
+ ### Library
163
+
164
+ **Basic Monitoring:**
165
+ ```python
166
+ import asyncio
167
+ from alpha_hwr import AlphaHWRClient
168
+
169
+ async def main():
170
+ async with AlphaHWRClient("DEVICE_UUID") as client:
171
+ # Authenticate first
172
+ await client.pair_device()
173
+
174
+ # Get single reading
175
+ telemetry = await client.read_telemetry()
176
+ print(f"Flow: {telemetry.flow_m3h} m3/h")
177
+
178
+ # Continuous monitoring
179
+ async for data in client.monitor():
180
+ print(data)
181
+
182
+ if __name__ == "__main__":
183
+ asyncio.run(main())
184
+ ```
185
+
186
+ **Reading Status Information:**
187
+ ```python
188
+ import asyncio
189
+ from alpha_hwr import AlphaHWRClient
190
+
191
+ async def main():
192
+ async with AlphaHWRClient("DEVICE_UUID") as client:
193
+ await client.pair_device()
194
+
195
+ # Get current control mode
196
+ mode = await client.get_control_mode()
197
+ print(f"Mode: {mode}")
198
+
199
+ # Read current setpoint with limits
200
+ setpoint = await client.read_current_setpoint(include_limits=True)
201
+ if setpoint:
202
+ value, unit = setpoint.get_display_value()
203
+ print(f"Setpoint: {value:.2f} {unit}")
204
+
205
+ if setpoint.min_setpoint:
206
+ limits = setpoint.get_limits_display()
207
+ if limits:
208
+ (min_val, min_unit), (max_val, max_unit) = limits
209
+ print(f"Limits: {min_val:.2f} - {max_val:.2f} {max_unit}")
210
+
211
+ # Check for alarms
212
+ alarms = await client.read_alarms()
213
+ if alarms and alarms.alarm_code and alarms.alarm_code != 0:
214
+ print(f"ALARM: {alarms.alarm_description}")
215
+
216
+ # Read cumulative statistics
217
+ stats = await client.read_statistics()
218
+ if stats:
219
+ print(f"Operating Hours: {stats.operating_hours:.1f} h")
220
+ print(f"Start Count: {stats.start_count}")
221
+
222
+ if __name__ == "__main__":
223
+ asyncio.run(main())
224
+ ```
225
+
226
+ **Setting Control Modes and Setpoints:**
227
+ ```python
228
+ import asyncio
229
+ from alpha_hwr import AlphaHWRClient
230
+
231
+ async def main():
232
+ async with AlphaHWRClient("DEVICE_UUID") as client:
233
+ await client.pair_device()
234
+
235
+ # Set constant pressure mode (automatic validation against limits)
236
+ success = await client.set_constant_pressure(1.5) # 1.5 meters
237
+ if success:
238
+ print("Pressure setpoint updated successfully")
239
+
240
+ # Set proportional pressure mode
241
+ success = await client.set_proportional_pressure(1.2) # 1.2 meters
242
+
243
+ # Set constant speed mode
244
+ success = await client.set_constant_speed(2500) # 2500 RPM
245
+
246
+ # Set constant flow mode
247
+ success = await client.set_constant_flow(2.0) # 2.0 m³/h
248
+
249
+ # Set AutoAdapt Radiator mode
250
+ success = await client.set_autoadapt_radiator(3.0) # 3.0 meters
251
+
252
+ # Set AutoAdapt Underfloor mode
253
+ success = await client.set_autoadapt_underfloor(2.5) # 2.5 meters
254
+
255
+ # Set AutoAdapt Radiator+Underfloor combined mode
256
+ success = await client.set_autoadapt_combined(3.5) # 3.5 meters
257
+
258
+ # Validate a setpoint before setting
259
+ is_valid, error = await client.validate_setpoint(
260
+ value=9804.0, # Pascals for pressure modes
261
+ control_mode=0, # Constant Pressure
262
+ strict=True
263
+ )
264
+ if not is_valid:
265
+ print(f"Invalid setpoint: {error}")
266
+
267
+ if __name__ == "__main__":
268
+ asyncio.run(main())
269
+ ```
270
+
271
+ **Schedule Management:**
272
+ ```python
273
+ import asyncio
274
+ from alpha_hwr import AlphaHWRClient
275
+ from alpha_hwr.models import ScheduleEntry
276
+
277
+ async def main():
278
+ async with AlphaHWRClient("DEVICE_UUID") as client:
279
+ await client.pair_device()
280
+
281
+ # Enable the schedule
282
+ await client.set_schedule_enabled(True)
283
+
284
+ # Set a schedule entry for Monday 06:00-08:30
285
+ success = await client.set_schedule_entry(
286
+ day="monday",
287
+ begin_hour=6,
288
+ begin_minute=0,
289
+ end_hour=8,
290
+ end_minute=30,
291
+ layer=0 # Layer 0-4 (supports 5 independent schedules)
292
+ )
293
+
294
+ # Set multiple entries at once
295
+ entries = [
296
+ ScheduleEntry(day="monday", begin_hour=6, begin_minute=0,
297
+ end_hour=8, end_minute=30, layer=0),
298
+ ScheduleEntry(day="tuesday", begin_hour=18, begin_minute=0,
299
+ end_hour=22, end_minute=0, layer=0),
300
+ ]
301
+ await client.set_weekly_schedule(entries, layer=0)
302
+
303
+ # Read current schedule
304
+ schedule = await client.read_weekly_schedule(layer=0)
305
+ for entry in schedule:
306
+ print(f"{entry.day}: {entry.begin_hour:02d}:{entry.begin_minute:02d} - "
307
+ f"{entry.end_hour:02d}:{entry.end_minute:02d}")
308
+
309
+ # Clear a specific day
310
+ await client.clear_schedule_entry("wednesday", layer=0)
311
+
312
+ # Clear entire layer
313
+ await client.clear_schedule_layer(layer=0)
314
+
315
+ # Export schedule to JSON
316
+ await client.export_schedule_json("schedule_backup.json")
317
+
318
+ # Import schedule from JSON
319
+ import json
320
+ with open("schedule_backup.json", "r") as f:
321
+ schedule_data = json.load(f)
322
+ # ... process and set schedule
323
+
324
+ if __name__ == "__main__":
325
+ asyncio.run(main())
326
+ ```
327
+
328
+ **Configuration Backup & Restore:**
329
+ ```python
330
+ import asyncio
331
+ from alpha_hwr import AlphaHWRClient
332
+
333
+ async def main():
334
+ async with AlphaHWRClient("DEVICE_UUID") as client:
335
+ await client.pair_device()
336
+
337
+ # Backup configuration
338
+ success = await client.backup_configuration("pump_backup.json")
339
+ if success:
340
+ print("Configuration backed up successfully")
341
+
342
+ # Restore configuration
343
+ success = await client.restore_configuration("pump_backup.json")
344
+ if success:
345
+ print("Configuration restored successfully")
346
+
347
+ if __name__ == "__main__":
348
+ asyncio.run(main())
349
+ ```
350
+
351
+ ## Supported Features
352
+
353
+ ### Control Modes
354
+
355
+ The ALPHA HWR supports **8 out of 32 GENI protocol control modes** (25%), specifically those needed for residential heating applications:
356
+
357
+ | Mode | Name | Status | Setpoint Range |
358
+ |------|------|--------|----------------|
359
+ | 0 | Constant Pressure | Fully Supported | 0.0 - 6.0 m |
360
+ | 1 | Proportional Pressure | Fully Supported | 0.0 - 6.0 m |
361
+ | 2 | Constant Speed | Fully Supported | 1000 - 4200 RPM |
362
+ | 8 | Constant Flow | Fully Supported | 0.0 - 4.5 m³/h |
363
+ | 5 | AutoAdapt (Generic) | Limited Support | 0.0 - 6.0 m (see docs) |
364
+ | 13 | AutoAdapt Radiator | Fully Supported | 0.0 - 6.0 m |
365
+ | 14 | AutoAdapt Underfloor | Fully Supported | 0.0 - 6.0 m |
366
+ | 15 | AutoAdapt Radiator+Underfloor | Fully Supported | 0.0 - 6.0 m |
367
+
368
+ **Unsupported Modes (24 total):** Chemical dosing (16-19), level control (9, 22), differential pressure (11, 12, 26), CEOPS/industrial modes (7, 10, 20-21, 23-25, 27-30, 128). See [Control Modes Matrix](https://eman.github.io/alpha-hwr/protocol/control_modes/) for details.
369
+
370
+ ### Advanced Features
371
+
372
+ | Feature | Status | Notes |
373
+ |---------|--------|-------|
374
+ | Real-time Telemetry | Supported | Flow, head, power, temp, voltage, current, RPM |
375
+ | Setpoint Limits | Supported | Min/max/default from factory config |
376
+ | Setpoint Validation | Supported | Automatic validation before writes |
377
+ | Alarm/Warning System | Supported | Current state only (98+ error codes) |
378
+ | Operating Statistics | Supported | Operating hours, start count |
379
+ | Weekly Schedules | Supported | 5 independent layers, full CRUD |
380
+ | Schedule Import/Export | Supported | JSON format |
381
+ | Config Backup/Restore | Supported | Full configuration backup |
382
+ | Historical Data | Supported | 100-cycle history for flow, head, temp, power |
383
+ | Event Log | Supported | Last 20 pump events with timestamps and modes |
384
+ | Multi-pump (CEOPS) | Not Available | Residential pump only |
385
+ | Cumulative Energy (kWh) | Not Available | Instantaneous power available |
386
+
387
+ ## Documentation
388
+
389
+ Complete documentation is available at [https://eman.github.io/alpha-hwr/](https://eman.github.io/alpha-hwr/).
390
+
391
+ * [**Getting Started**](https://eman.github.io/alpha-hwr/getting_started/installation/)
392
+ * [**CLI Guide**](https://eman.github.io/alpha-hwr/guides/cli_guide/)
393
+ * [**API Reference**](https://eman.github.io/alpha-hwr/api/client/)
394
+ * [**Protocol Details**](https://eman.github.io/alpha-hwr/protocol/ble_architecture/)
395
+
396
+ ## Project Status
397
+
398
+ **Status:** Production-ready for ALPHA HWR series.
399
+
400
+ **Test Coverage:** 204 passing tests, 100% of hardware features tested on real ALPHA HWR pump.
401
+
402
+ **Key Features Implemented:**
403
+ - Real-time telemetry (Flow, Head, Power, Temp, Electrical)
404
+ - Full motor control (Start/Stop, Mode switching)
405
+ - Advanced setpoint management with validation
406
+ - Comprehensive weekly schedule management (5 layers)
407
+ - Configuration backup and restore
408
+ - Detailed device information (Serial, Firmware)
409
+
410
+ ## Contributing
411
+
412
+ Contributions are welcome! Please ensure:
413
+ - All tests pass (`tox`)
414
+ - Code follows project style (ruff, mypy, basedpyright)
415
+ - New features include tests and documentation
416
+
417
+ ## License
418
+
419
+ See LICENSE file for details.