flameconnect 0.1.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.
- flameconnect-0.1.0/.ai/task-manager/.init-metadata.json +18 -0
- flameconnect-0.1.0/.ai/task-manager/README.md +7 -0
- flameconnect-0.1.0/.ai/task-manager/archive/01--project-foundation/plan-01--project-foundation.md +401 -0
- flameconnect-0.1.0/.ai/task-manager/archive/01--project-foundation/tasks/01--project-scaffolding.md +126 -0
- flameconnect-0.1.0/.ai/task-manager/archive/01--project-foundation/tasks/02--models-constants-exceptions.md +108 -0
- flameconnect-0.1.0/.ai/task-manager/archive/01--project-foundation/tasks/03--wire-protocol.md +83 -0
- flameconnect-0.1.0/.ai/task-manager/archive/01--project-foundation/tasks/04--auth-module.md +97 -0
- flameconnect-0.1.0/.ai/task-manager/archive/01--project-foundation/tasks/05--async-client.md +133 -0
- flameconnect-0.1.0/.ai/task-manager/archive/01--project-foundation/tasks/06--tests-protocol-and-client.md +115 -0
- flameconnect-0.1.0/.ai/task-manager/archive/01--project-foundation/tasks/07--cli-tool.md +133 -0
- flameconnect-0.1.0/.ai/task-manager/archive/01--project-foundation/tasks/08--tui-dashboard.md +127 -0
- flameconnect-0.1.0/.ai/task-manager/archive/01--project-foundation/tasks/09--ci-cd-workflows.md +145 -0
- flameconnect-0.1.0/.ai/task-manager/archive/01--project-foundation/tasks/10--readme.md +116 -0
- flameconnect-0.1.0/.ai/task-manager/archive/02--fireplace-state-controls/plan-02--fireplace-state-controls.md +259 -0
- flameconnect-0.1.0/.ai/task-manager/archive/02--fireplace-state-controls/tasks/01--refactor-dataclasses-replace.md +47 -0
- flameconnect-0.1.0/.ai/task-manager/archive/02--fireplace-state-controls/tasks/02--add-cli-set-commands.md +53 -0
- flameconnect-0.1.0/.ai/task-manager/archive/02--fireplace-state-controls/tasks/03--add-tui-keybindings.md +67 -0
- flameconnect-0.1.0/.ai/task-manager/archive/02--fireplace-state-controls/tasks/04--add-tests.md +61 -0
- flameconnect-0.1.0/.ai/task-manager/archive/03--flame-effect-controls/plan-03--flame-effect-controls.md +315 -0
- flameconnect-0.1.0/.ai/task-manager/archive/03--flame-effect-controls/tasks/01--named-colors-and-cli-commands.md +167 -0
- flameconnect-0.1.0/.ai/task-manager/archive/03--flame-effect-controls/tasks/02--flame-color-and-media-theme-screens.md +127 -0
- flameconnect-0.1.0/.ai/task-manager/archive/03--flame-effect-controls/tasks/03--color-screen.md +185 -0
- flameconnect-0.1.0/.ai/task-manager/archive/03--flame-effect-controls/tasks/04--tui-keybindings-and-actions.md +270 -0
- flameconnect-0.1.0/.ai/task-manager/archive/03--flame-effect-controls/tasks/05--tests.md +231 -0
- flameconnect-0.1.0/.ai/task-manager/archive/04--tui-visual-polish/plan-04--tui-visual-polish.md +351 -0
- flameconnect-0.1.0/.ai/task-manager/archive/04--tui-visual-polish/tasks/01--widgets-formatter-overhaul.md +104 -0
- flameconnect-0.1.0/.ai/task-manager/archive/04--tui-visual-polish/tasks/02--layout-footer-help-info.md +131 -0
- flameconnect-0.1.0/.ai/task-manager/archive/04--tui-visual-polish/tasks/03--heat-mode-fire-switcher-dialogs.md +144 -0
- flameconnect-0.1.0/.ai/task-manager/archive/04--tui-visual-polish/tasks/04--tests.md +139 -0
- flameconnect-0.1.0/.ai/task-manager/archive/05--fireplace-visual-overhaul/plan-05--fireplace-visual-overhaul.md +256 -0
- flameconnect-0.1.0/.ai/task-manager/archive/05--fireplace-visual-overhaul/tasks/01--rewrite-fireplace-visual-rendering.md +54 -0
- flameconnect-0.1.0/.ai/task-manager/archive/05--fireplace-visual-overhaul/tasks/02--wire-dashboard-state-to-visual.md +39 -0
- flameconnect-0.1.0/.ai/task-manager/archive/05--fireplace-visual-overhaul/tasks/03--add-tests-for-new-rendering.md +48 -0
- flameconnect-0.1.0/.ai/task-manager/archive/06--responsive-tui-layout/plan-06--responsive-tui-layout.md +226 -0
- flameconnect-0.1.0/.ai/task-manager/archive/06--responsive-tui-layout/tasks/01--implement-responsive-layout.md +60 -0
- flameconnect-0.1.0/.ai/task-manager/archive/06--responsive-tui-layout/tasks/02--add-responsive-layout-tests.md +46 -0
- flameconnect-0.1.0/.ai/task-manager/archive/07--tui-fixes-and-features/plan-07--tui-fixes-and-features.md +437 -0
- flameconnect-0.1.0/.ai/task-manager/archive/07--tui-fixes-and-features/tasks/01--fix-parameter-panel-border.md +49 -0
- flameconnect-0.1.0/.ai/task-manager/archive/07--tui-fixes-and-features/tasks/02--version-header-and-help-toggle.md +46 -0
- flameconnect-0.1.0/.ai/task-manager/archive/07--tui-fixes-and-features/tasks/03--label-rename-and-temp-unit-display.md +54 -0
- flameconnect-0.1.0/.ai/task-manager/archive/07--tui-fixes-and-features/tasks/04--dialog-ux-improvements.md +57 -0
- flameconnect-0.1.0/.ai/task-manager/archive/07--tui-fixes-and-features/tasks/05--flame-animation-and-heat-visual.md +65 -0
- flameconnect-0.1.0/.ai/task-manager/archive/07--tui-fixes-and-features/tasks/06--media-theme-investigation.md +42 -0
- flameconnect-0.1.0/.ai/task-manager/archive/07--tui-fixes-and-features/tasks/07--clickable-parameter-fields.md +96 -0
- flameconnect-0.1.0/.ai/task-manager/archive/07--tui-fixes-and-features/tasks/08--temperature-adjustment-dialog.md +73 -0
- flameconnect-0.1.0/.ai/task-manager/archive/08--tui-refinements/plan-08--tui-refinements.md +319 -0
- flameconnect-0.1.0/.ai/task-manager/archive/08--tui-refinements/tasks/01--clickable-values-only.md +59 -0
- flameconnect-0.1.0/.ai/task-manager/archive/08--tui-refinements/tasks/02--git-hash-and-label-renames.md +63 -0
- flameconnect-0.1.0/.ai/task-manager/archive/08--tui-refinements/tasks/03--fireplace-visual-refinements.md +71 -0
- flameconnect-0.1.0/.ai/task-manager/archive/08--tui-refinements/tasks/04--temperature-conversion.md +78 -0
- flameconnect-0.1.0/.ai/task-manager/archive/09--tui-bug-fixes/plan-09--tui-bug-fixes.md +167 -0
- flameconnect-0.1.0/.ai/task-manager/archive/09--tui-bug-fixes/tasks/01--fix-flame-effect-graphic.md +55 -0
- flameconnect-0.1.0/.ai/task-manager/archive/09--tui-bug-fixes/tasks/02--fix-click-values.md +49 -0
- flameconnect-0.1.0/.ai/task-manager/archive/09--tui-bug-fixes/tasks/03--fix-duplicate-overhead-light.md +53 -0
- flameconnect-0.1.0/.ai/task-manager/archive/10--pytest-cov-integration/plan-10--pytest-cov-integration.md +139 -0
- flameconnect-0.1.0/.ai/task-manager/archive/10--pytest-cov-integration/tasks/01--add-pytest-cov-dependency-and-config.md +37 -0
- flameconnect-0.1.0/.ai/task-manager/archive/10--pytest-cov-integration/tasks/02--update-ci-pytest-command.md +35 -0
- flameconnect-0.1.0/.ai/task-manager/archive/11--increase-test-coverage/plan-11--increase-test-coverage.md +186 -0
- flameconnect-0.1.0/.ai/task-manager/archive/11--increase-test-coverage/tasks/01--cli-command-display-tests.md +47 -0
- flameconnect-0.1.0/.ai/task-manager/archive/11--increase-test-coverage/tasks/02--tui-app-action-tests.md +46 -0
- flameconnect-0.1.0/.ai/task-manager/archive/11--increase-test-coverage/tasks/03--tui-widget-format-tests.md +44 -0
- flameconnect-0.1.0/.ai/task-manager/archive/11--increase-test-coverage/tasks/04--tui-screen-tests.md +58 -0
- flameconnect-0.1.0/.ai/task-manager/archive/11--increase-test-coverage/tasks/05--core-module-edge-case-tests.md +49 -0
- flameconnect-0.1.0/.ai/task-manager/config/TASK_MANAGER.md +109 -0
- flameconnect-0.1.0/.ai/task-manager/config/hooks/POST_ERROR_DETECTION.md +48 -0
- flameconnect-0.1.0/.ai/task-manager/config/hooks/POST_PHASE.md +24 -0
- flameconnect-0.1.0/.ai/task-manager/config/hooks/POST_PLAN.md +3 -0
- flameconnect-0.1.0/.ai/task-manager/config/hooks/POST_TASK_GENERATION_ALL.md +162 -0
- flameconnect-0.1.0/.ai/task-manager/config/hooks/PRE_PHASE.md +28 -0
- flameconnect-0.1.0/.ai/task-manager/config/hooks/PRE_PLAN.md +58 -0
- flameconnect-0.1.0/.ai/task-manager/config/hooks/PRE_TASK_ASSIGNMENT.md +84 -0
- flameconnect-0.1.0/.ai/task-manager/config/scripts/check-task-dependencies.cjs +357 -0
- flameconnect-0.1.0/.ai/task-manager/config/scripts/compose-prompt.cjs +234 -0
- flameconnect-0.1.0/.ai/task-manager/config/scripts/detect-assistant.cjs +67 -0
- flameconnect-0.1.0/.ai/task-manager/config/scripts/get-next-plan-id.cjs +431 -0
- flameconnect-0.1.0/.ai/task-manager/config/scripts/get-next-task-id.cjs +160 -0
- flameconnect-0.1.0/.ai/task-manager/config/scripts/package-lock.json +49 -0
- flameconnect-0.1.0/.ai/task-manager/config/scripts/package.json +5 -0
- flameconnect-0.1.0/.ai/task-manager/config/scripts/read-assistant-config.cjs +99 -0
- flameconnect-0.1.0/.ai/task-manager/config/scripts/validate-plan-blueprint.cjs +333 -0
- flameconnect-0.1.0/.ai/task-manager/config/templates/BLUEPRINT_TEMPLATE.md +26 -0
- flameconnect-0.1.0/.ai/task-manager/config/templates/EXECUTION_SUMMARY_TEMPLATE.md +13 -0
- flameconnect-0.1.0/.ai/task-manager/config/templates/PLAN_TEMPLATE.md +92 -0
- flameconnect-0.1.0/.ai/task-manager/config/templates/TASK_TEMPLATE.md +36 -0
- flameconnect-0.1.0/.ai/task-manager/plans/12--mutation-testing-expansion/plan-12--mutation-testing-expansion.md +141 -0
- flameconnect-0.1.0/.ai/task-manager/plans/12--mutation-testing-expansion/tasks/01--mutmut-config-and-ci.md +27 -0
- flameconnect-0.1.0/.ai/task-manager/plans/12--mutation-testing-expansion/tasks/02--kill-protocol-mutants.md +28 -0
- flameconnect-0.1.0/.ai/task-manager/plans/12--mutation-testing-expansion/tasks/03--kill-client-mutants.md +27 -0
- flameconnect-0.1.0/.ai/task-manager/plans/12--mutation-testing-expansion/tasks/04--kill-auth-mutants.md +27 -0
- flameconnect-0.1.0/.ai/task-manager/plans/12--mutation-testing-expansion/tasks/05--kill-b2c-mutants.md +27 -0
- flameconnect-0.1.0/.claude/agents/plan-creator.md +95 -0
- flameconnect-0.1.0/.claude/commands/tasks/create-plan.md +144 -0
- flameconnect-0.1.0/.claude/commands/tasks/execute-blueprint.md +191 -0
- flameconnect-0.1.0/.claude/commands/tasks/execute-task.md +259 -0
- flameconnect-0.1.0/.claude/commands/tasks/fix-broken-tests.md +39 -0
- flameconnect-0.1.0/.claude/commands/tasks/full-workflow.md +437 -0
- flameconnect-0.1.0/.claude/commands/tasks/generate-tasks.md +321 -0
- flameconnect-0.1.0/.claude/commands/tasks/refine-plan.md +130 -0
- flameconnect-0.1.0/.github/workflows/ci.yml +29 -0
- flameconnect-0.1.0/.github/workflows/conventional-commits.yml +14 -0
- flameconnect-0.1.0/.github/workflows/publish-to-pypi.yml +69 -0
- flameconnect-0.1.0/.github/workflows/release.yml +41 -0
- flameconnect-0.1.0/.gitignore +14 -0
- flameconnect-0.1.0/.pre-commit-config.yaml +30 -0
- flameconnect-0.1.0/CHANGELOG.md +108 -0
- flameconnect-0.1.0/FLAMECONNECT_API_REPORT.md +1059 -0
- flameconnect-0.1.0/LICENSE +199 -0
- flameconnect-0.1.0/PKG-INFO +292 -0
- flameconnect-0.1.0/README.md +270 -0
- flameconnect-0.1.0/images/flameconnect-0.1.0.png +0 -0
- flameconnect-0.1.0/pyproject.toml +52 -0
- flameconnect-0.1.0/renovate.json +8 -0
- flameconnect-0.1.0/setup.cfg +7 -0
- flameconnect-0.1.0/src/flameconnect/__init__.py +86 -0
- flameconnect-0.1.0/src/flameconnect/__main__.py +3 -0
- flameconnect-0.1.0/src/flameconnect/auth.py +213 -0
- flameconnect-0.1.0/src/flameconnect/b2c_login.py +327 -0
- flameconnect-0.1.0/src/flameconnect/cli.py +996 -0
- flameconnect-0.1.0/src/flameconnect/client.py +288 -0
- flameconnect-0.1.0/src/flameconnect/const.py +47 -0
- flameconnect-0.1.0/src/flameconnect/exceptions.py +23 -0
- flameconnect-0.1.0/src/flameconnect/models.py +313 -0
- flameconnect-0.1.0/src/flameconnect/protocol.py +473 -0
- flameconnect-0.1.0/src/flameconnect/py.typed +0 -0
- flameconnect-0.1.0/src/flameconnect/tui/__init__.py +7 -0
- flameconnect-0.1.0/src/flameconnect/tui/app.py +1086 -0
- flameconnect-0.1.0/src/flameconnect/tui/auth_screen.py +224 -0
- flameconnect-0.1.0/src/flameconnect/tui/color_screen.py +175 -0
- flameconnect-0.1.0/src/flameconnect/tui/fire_select_screen.py +118 -0
- flameconnect-0.1.0/src/flameconnect/tui/flame_color_screen.py +108 -0
- flameconnect-0.1.0/src/flameconnect/tui/flame_speed_screen.py +89 -0
- flameconnect-0.1.0/src/flameconnect/tui/heat_mode_screen.py +158 -0
- flameconnect-0.1.0/src/flameconnect/tui/media_theme_screen.py +122 -0
- flameconnect-0.1.0/src/flameconnect/tui/screens.py +308 -0
- flameconnect-0.1.0/src/flameconnect/tui/temperature_screen.py +154 -0
- flameconnect-0.1.0/src/flameconnect/tui/timer_screen.py +118 -0
- flameconnect-0.1.0/src/flameconnect/tui/widgets.py +1003 -0
- flameconnect-0.1.0/tests/__init__.py +0 -0
- flameconnect-0.1.0/tests/conftest.py +30 -0
- flameconnect-0.1.0/tests/fixtures/get_fire_overview.json +55 -0
- flameconnect-0.1.0/tests/fixtures/get_fires.json +13 -0
- flameconnect-0.1.0/tests/test_auth.py +814 -0
- flameconnect-0.1.0/tests/test_b2c_login.py +1164 -0
- flameconnect-0.1.0/tests/test_cli_commands.py +1669 -0
- flameconnect-0.1.0/tests/test_cli_set.py +815 -0
- flameconnect-0.1.0/tests/test_client.py +1220 -0
- flameconnect-0.1.0/tests/test_fireplace_visual.py +312 -0
- flameconnect-0.1.0/tests/test_main.py +18 -0
- flameconnect-0.1.0/tests/test_models.py +201 -0
- flameconnect-0.1.0/tests/test_protocol.py +1563 -0
- flameconnect-0.1.0/tests/test_responsive_layout.py +89 -0
- flameconnect-0.1.0/tests/test_tui_actions.py +3296 -0
- flameconnect-0.1.0/tests/test_tui_screens.py +1908 -0
- flameconnect-0.1.0/tests/test_widgets_format.py +1126 -0
- flameconnect-0.1.0/uv.lock +1252 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.26.0",
|
|
3
|
+
"timestamp": "2026-02-23T15:47:51.120Z",
|
|
4
|
+
"files": {
|
|
5
|
+
"config/TASK_MANAGER.md": "ad37290f6f5bced23be611198f288f8c196452183aa139197085c3da73174b49",
|
|
6
|
+
"config/hooks/POST_ERROR_DETECTION.md": "ed4e1691880ea54ea43c318dc236c326ed81a3ce2785321a25e6db747a6e7e88",
|
|
7
|
+
"config/hooks/POST_PHASE.md": "d79fccfee4629ffc226db97f6f755c4dd068ee9c30f7d8bf98dfc55b104003c5",
|
|
8
|
+
"config/hooks/POST_PLAN.md": "4c9850cb6d11d74065b6c4a00137fe00540aeea7b44d9edbfc8211ff5ea34662",
|
|
9
|
+
"config/hooks/POST_TASK_GENERATION_ALL.md": "aa86468a634da40ae141670b960473bce10589190b0f9119bf07d64cd49a9a7b",
|
|
10
|
+
"config/hooks/PRE_PHASE.md": "efd9ad1ae9265ef36388cd5dfd9f96a45ae98f7f3d1a2eb5cc8caec01f4efb23",
|
|
11
|
+
"config/hooks/PRE_PLAN.md": "b8291630f12a1745e00b4a8079e9b7d8d5f7cd3c146df505b2fc8fa175dea1b9",
|
|
12
|
+
"config/hooks/PRE_TASK_ASSIGNMENT.md": "94735720070a6084560cc89708deb1e123f8c8b24c9ed8ffbb95886423d4b9f7",
|
|
13
|
+
"config/templates/BLUEPRINT_TEMPLATE.md": "f67488cd05a2fcdbf8a58a863d1315cde4f77a3b42d7e752374feb31620e8063",
|
|
14
|
+
"config/templates/EXECUTION_SUMMARY_TEMPLATE.md": "9023bd2f6e39169068fd8684254679c82bc76ddbde3d2881eadd76c107f083c2",
|
|
15
|
+
"config/templates/PLAN_TEMPLATE.md": "c506f6f9394bc4b75e4ccc9fafcef244219bb255a9efd7b95852e8f21123728b",
|
|
16
|
+
"config/templates/TASK_TEMPLATE.md": "e0fa4d9bde7d9ab9edcf4f32785011c7125424f5199a0994c5900ef0352c4e02"
|
|
17
|
+
}
|
|
18
|
+
}
|
flameconnect-0.1.0/.ai/task-manager/archive/01--project-foundation/plan-01--project-foundation.md
ADDED
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: 1
|
|
3
|
+
summary: "Transform flameconnect from a standalone script into a fully-packaged async Python library with CLI, TUI, testing, CI/CD, and PyPI publishing"
|
|
4
|
+
created: 2026-02-23
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Plan: FlameConnect Project Foundation
|
|
8
|
+
|
|
9
|
+
## Original Work Order
|
|
10
|
+
> Create a plan to implement all project philosophy and technology choices in the .ai/task-manager/config/TASK_MANAGER.md file.
|
|
11
|
+
|
|
12
|
+
## Plan Clarifications
|
|
13
|
+
|
|
14
|
+
| Question | Answer |
|
|
15
|
+
|----------|--------|
|
|
16
|
+
| Async strategy | Fully async: aiohttp for HTTP, msal wrapped with asyncio.to_thread() |
|
|
17
|
+
| Package name | `flameconnect` (confirmed available on PyPI) |
|
|
18
|
+
| Home Assistant integration | Library + CLI only; HA integration is a separate future project |
|
|
19
|
+
| API endpoint scope | Core control endpoints: GetFires, GetFireOverview, WriteWifiParameters. Note: there is no separate ReadWifiParameters endpoint — parameter reading is done via GetFireOverview. README documents what is and isn't implemented. |
|
|
20
|
+
| Auth library | msal with async wrapper (msal is well-tested for Azure AD B2C) |
|
|
21
|
+
| TUI mode | Included in this plan using textual |
|
|
22
|
+
| TUI dependency | Optional packaging extra: `pip install flameconnect[tui]` / `uv add flameconnect[tui]`. Keeps base library lightweight for HA consumers. |
|
|
23
|
+
| Mutation testing | Runs in the main CI pipeline on every push/PR alongside ruff, mypy, and pytest. |
|
|
24
|
+
| Live API testing | Permitted during development. Before making any live API call: explain what the call does, ask the user for confirmation, then ask if the result matched expectations. CI tests still use fixtures/mocks only. |
|
|
25
|
+
|
|
26
|
+
## Executive Summary
|
|
27
|
+
|
|
28
|
+
This plan transforms the existing `flameconnect_reader.py` standalone script into a production-quality, async-first Python library with a CLI and TUI interface. The project currently exists as a single 570-line script using synchronous `requests` and `msal` with no packaging, tests, type annotations, linting, or CI/CD.
|
|
29
|
+
|
|
30
|
+
The approach restructures the code into a proper Python package managed by `uv`, replaces synchronous HTTP calls with `aiohttp`, adds strict type annotations enforced by `mypy`, comprehensive tests with `pytest` and mutation testing via `mutmut`, a CLI tool, a textual-based TUI, and a complete CI/CD pipeline using GitHub Actions with conventional commits and release-please for automated releases to PyPI.
|
|
31
|
+
|
|
32
|
+
The plan prioritizes the three core control endpoints (GetFires, GetFireOverview, WriteWifiParameters) which together cover fireplace discovery, state reading, and parameter control. The remaining 30+ API endpoints are documented as future work in the README.
|
|
33
|
+
|
|
34
|
+
## Context
|
|
35
|
+
|
|
36
|
+
### Current State vs Target State
|
|
37
|
+
|
|
38
|
+
| Current State | Target State | Why? |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| Single script (`flameconnect_reader.py`, 570 lines) | Proper Python package with modular structure | Enables import as library, distribution via PyPI, and consumption by Home Assistant |
|
|
41
|
+
| Synchronous HTTP via `requests` | Async HTTP via `aiohttp` | Home Assistant is fully async; sync wrappers in executors add overhead and complexity |
|
|
42
|
+
| No type annotations in code | Full type annotations, mypy strict mode | Catches bugs at development time, enables IDE support, required by HA contribution guidelines |
|
|
43
|
+
| No tests (0% coverage) | pytest with fixtures + mutmut mutation testing | Ensures correctness, prevents regressions, validates test quality |
|
|
44
|
+
| No packaging (pyproject.toml, etc.) | uv-managed project with pyproject.toml | Enables dependency management, versioning, and PyPI distribution |
|
|
45
|
+
| No linting or formatting | ruff for linting + formatting | Consistent code style, catches common errors |
|
|
46
|
+
| No CI/CD | GitHub Actions workflows | Automated testing, linting, release management |
|
|
47
|
+
| No versioning or releases | Conventional commits + release-please + PyPI | Automated semantic versioning and package publishing |
|
|
48
|
+
| Hardcoded MSAL browser login only | Token injection + built-in credential handling | Supports both Home Assistant (token injection) and standalone use (browser login) |
|
|
49
|
+
| No CLI interface | CLI tool built on the async library | Command-line access to all fireplace operations |
|
|
50
|
+
| No TUI | Textual-based TUI mode | Interactive dashboard showing fireplace status and controls |
|
|
51
|
+
| README is an API report | Human-oriented README with usage docs | Clear onboarding for users and contributors |
|
|
52
|
+
| Uses `print()` for output | stdlib `logging` module | Proper log levels, follows HA conventions, no print() in library code |
|
|
53
|
+
|
|
54
|
+
### Background
|
|
55
|
+
|
|
56
|
+
The flameconnect project was created by reverse-engineering the Flame Connect Android APK (v2.22.0). The API report (`FLAMECONNECT_API_REPORT.md`) documents 30+ endpoints and a binary wire protocol for fireplace parameter control. The existing script demonstrates that the API integration works correctly - the challenge is now restructuring it into a well-engineered library.
|
|
57
|
+
|
|
58
|
+
Key constraints:
|
|
59
|
+
- **Minimal dependencies**: Prioritize packages already in Home Assistant (aiohttp is included, msal is not but is necessary for standalone auth)
|
|
60
|
+
- **Azure AD B2C auth**: The upstream API uses Microsoft's B2C tenant, making msal the most reliable auth option
|
|
61
|
+
- **Binary wire protocol**: Parameters use a base64-encoded binary format that must be carefully preserved during refactoring
|
|
62
|
+
- **Live API calls permitted during development**: To validate that the refactored code works against the real API, live calls are allowed during development. However, a strict protocol must be followed: (1) explain to the user what API call will be made and why, (2) get explicit user confirmation before making it, (3) ask the user to verify whether the result was correct. This respects the upstream API (no spam) while enabling real-world validation.
|
|
63
|
+
- **CI tests use fixtures/mocks only**: Automated tests must never make live API calls. All CI test fixtures should be derived from real API responses captured during development.
|
|
64
|
+
|
|
65
|
+
## Architectural Approach
|
|
66
|
+
|
|
67
|
+
```mermaid
|
|
68
|
+
graph TB
|
|
69
|
+
subgraph "Package: flameconnect"
|
|
70
|
+
direction TB
|
|
71
|
+
A[auth.py<br/>Token injection + MSAL] --> B[client.py<br/>Async API client]
|
|
72
|
+
B --> D[protocol.py<br/>Binary wire encoding/decoding]
|
|
73
|
+
B --> C[models.py<br/>Dataclasses + enums]
|
|
74
|
+
D --> C
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
subgraph "Interfaces"
|
|
78
|
+
E[cli.py<br/>CLI commands] --> B
|
|
79
|
+
F[tui/<br/>Textual dashboard] --> B
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
subgraph "Infrastructure"
|
|
83
|
+
G[pyproject.toml<br/>uv, ruff, mypy config]
|
|
84
|
+
H[GitHub Actions<br/>CI/CD workflows]
|
|
85
|
+
I[Tests<br/>pytest + mutmut]
|
|
86
|
+
end
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Package Structure
|
|
90
|
+
**Objective**: Organize the codebase into a proper Python package with clear module boundaries.
|
|
91
|
+
|
|
92
|
+
The `flameconnect` package will be structured as:
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
src/flameconnect/
|
|
96
|
+
__init__.py # Public API exports
|
|
97
|
+
__main__.py # Entry point for `python -m flameconnect`
|
|
98
|
+
py.typed # PEP 561 marker for typed package (enables mypy for consumers)
|
|
99
|
+
auth.py # Authentication (token injection + MSAL credential flow)
|
|
100
|
+
client.py # FlameConnectClient - async API client
|
|
101
|
+
models.py # Dataclasses for API responses, enums, typed parameters
|
|
102
|
+
protocol.py # Binary wire protocol encoding/decoding
|
|
103
|
+
exceptions.py # Custom exception hierarchy
|
|
104
|
+
const.py # Constants (API URLs, headers, parameter IDs)
|
|
105
|
+
cli.py # CLI entry point using argparse (stdlib, zero extra dependencies)
|
|
106
|
+
tui/
|
|
107
|
+
__init__.py
|
|
108
|
+
app.py # Textual App subclass
|
|
109
|
+
screens.py # TUI screens (dashboard, control)
|
|
110
|
+
widgets.py # Custom widgets (flame display, heat controls)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
The `src/` layout is used because it prevents accidental imports of the uninstalled package and is the modern Python packaging standard. The `py.typed` marker file (PEP 561) signals to mypy that this package ships inline type annotations, enabling type checking for downstream consumers.
|
|
114
|
+
|
|
115
|
+
### Async Client Design
|
|
116
|
+
**Objective**: Provide a clean async API that supports both Home Assistant token injection and standalone credential handling.
|
|
117
|
+
|
|
118
|
+
The `FlameConnectClient` will accept an `aiohttp.ClientSession` (optional, creates its own if not provided) and authentication via either:
|
|
119
|
+
1. **Token injection**: A string token or an `async callable` that returns a token (for Home Assistant)
|
|
120
|
+
2. **Built-in credentials**: MSAL-based browser login with persistent token cache (for CLI/standalone use)
|
|
121
|
+
|
|
122
|
+
The client will be an async context manager:
|
|
123
|
+
```python
|
|
124
|
+
async with FlameConnectClient(auth=token_provider) as client:
|
|
125
|
+
fires = await client.get_fires()
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
All API methods return typed dataclasses from `models.py`, not raw dicts. The binary wire protocol is encapsulated in `protocol.py` so callers never deal with base64/struct directly.
|
|
129
|
+
|
|
130
|
+
### Models and Type System
|
|
131
|
+
**Objective**: Replace raw dicts and magic numbers with typed dataclasses and enums enforced by mypy strict mode.
|
|
132
|
+
|
|
133
|
+
All API responses will be represented as `dataclass` or `NamedTuple` types. The existing enum mappings (FIRE_MODE, FLAME_EFFECT, HEAT_STATUS, etc.) become proper Python `Enum` classes. Parameter types will use typed dataclasses with proper field definitions.
|
|
134
|
+
|
|
135
|
+
The wire protocol encoding/decoding in `protocol.py` will accept and return these typed models, providing a clean boundary between the binary format and the rest of the library. Note: the existing script has incomplete decoders — Sound (369) and Log Effect (370) have display code but no binary decoding logic, and only Mode (321) and Flame Effect (322) have encoders. All 11 parameter types (236, 321, 322, 323, 325, 326, 327, 329, 369, 370) must have complete decode implementations, with encode implementations for all writable parameters. The `FLAMECONNECT_API_REPORT.md` documents the wire format for each.
|
|
136
|
+
|
|
137
|
+
### CLI Tool
|
|
138
|
+
**Objective**: Provide command-line access to all fireplace operations.
|
|
139
|
+
|
|
140
|
+
The CLI will use Python's `argparse` from stdlib (zero extra dependencies, aligning with the minimal-dependencies philosophy) to expose commands:
|
|
141
|
+
- `flameconnect list` - List registered fireplaces
|
|
142
|
+
- `flameconnect status <fire_id>` - Show current fireplace state
|
|
143
|
+
- `flameconnect on <fire_id>` - Turn on fireplace
|
|
144
|
+
- `flameconnect off <fire_id>` - Turn off fireplace
|
|
145
|
+
- `flameconnect set <fire_id> <param> <value>` - Set parameters (flame, heat, timer, etc.)
|
|
146
|
+
- `flameconnect tui` - Launch the textual TUI
|
|
147
|
+
|
|
148
|
+
The CLI will use `asyncio.run()` to bridge sync entry points to the async library. Authentication will use the built-in MSAL credential flow with token caching.
|
|
149
|
+
|
|
150
|
+
### TUI Dashboard
|
|
151
|
+
**Objective**: Provide an interactive terminal interface for monitoring and controlling fireplaces using textual.
|
|
152
|
+
|
|
153
|
+
The TUI will be a textual `App` that displays:
|
|
154
|
+
- A list of registered fireplaces with connection status
|
|
155
|
+
- A dashboard view for the selected fireplace showing:
|
|
156
|
+
- Current mode (standby/manual)
|
|
157
|
+
- Flame effect settings (speed, brightness, color)
|
|
158
|
+
- Heat settings (status, temperature, mode)
|
|
159
|
+
- Timer status
|
|
160
|
+
- Error codes (if any)
|
|
161
|
+
- Interactive controls for toggling power, adjusting flame/heat settings
|
|
162
|
+
- Auto-refresh of fireplace state on a configurable interval
|
|
163
|
+
|
|
164
|
+
The TUI will be launched via `flameconnect tui` and requires the optional `tui` extra (`pip install flameconnect[tui]` or `uv add flameconnect[tui]`). The `textual` import is lazy — it only occurs when the `tui` command is invoked, so the base library remains lightweight for consumers like Home Assistant. If a user runs `flameconnect tui` without the extra installed, they will get a clear error message with installation instructions.
|
|
165
|
+
|
|
166
|
+
### Testing Strategy
|
|
167
|
+
**Objective**: Achieve high test coverage through two complementary approaches — automated fixture-based tests for CI, and live API validation during development.
|
|
168
|
+
|
|
169
|
+
**Automated tests (CI)**: Tests will use `pytest` with `aiohttp` test utilities and `pytest-aiohttp` for async test support. All API responses will be captured as JSON fixtures. Mutation testing with `mutmut` validates that tests catch real code changes.
|
|
170
|
+
|
|
171
|
+
**Live API validation (development)**: During implementation, the developer may make real API calls to validate correctness. This follows a strict three-step protocol:
|
|
172
|
+
1. **Explain**: Describe the API call (endpoint, parameters, expected effect)
|
|
173
|
+
2. **Confirm**: Wait for explicit user approval before executing
|
|
174
|
+
3. **Verify**: Ask the user to confirm whether the result matched expectations
|
|
175
|
+
|
|
176
|
+
This enables capturing real API response shapes for fixtures and verifying that encoded parameters produce the expected fireplace behavior. Live validation is especially valuable for the wire protocol (Task 03), async client (Task 05), and CLI (Task 07).
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
tests/
|
|
180
|
+
conftest.py # Shared fixtures, mock session factory
|
|
181
|
+
test_auth.py # Auth token injection and MSAL flow tests
|
|
182
|
+
test_client.py # API client method tests with mocked responses
|
|
183
|
+
test_models.py # Dataclass construction and validation
|
|
184
|
+
test_protocol.py # Wire protocol encode/decode round-trip tests
|
|
185
|
+
test_cli.py # CLI argument parsing and command execution
|
|
186
|
+
fixtures/ # JSON response fixtures derived from real API responses
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### CI/CD Pipeline
|
|
190
|
+
**Objective**: Automate linting, testing, and release management via GitHub Actions.
|
|
191
|
+
|
|
192
|
+
Three workflows:
|
|
193
|
+
1. **CI** (on push/PR): Run ruff lint + format check, mypy strict, pytest, and mutmut mutation testing. All checks must pass before merge.
|
|
194
|
+
2. **Conventional Commits** (on PR): Validate PR title and commit messages follow conventional commit format.
|
|
195
|
+
3. **Release** (on merge to main): release-please creates release PRs with changelog; on release, build and publish to PyPI. Initial version will be 0.1.0.
|
|
196
|
+
|
|
197
|
+
### Logging
|
|
198
|
+
**Objective**: Replace all `print()` calls with stdlib `logging` following Home Assistant conventions.
|
|
199
|
+
|
|
200
|
+
The library will use `logging.getLogger(__name__)` in each module. No `print()` in library code. The CLI/TUI will configure log handlers and levels. Debug logging will include API request/response details for troubleshooting.
|
|
201
|
+
|
|
202
|
+
## Risk Considerations and Mitigation Strategies
|
|
203
|
+
|
|
204
|
+
<details>
|
|
205
|
+
<summary>Technical Risks</summary>
|
|
206
|
+
|
|
207
|
+
- **MSAL async wrapping**: msal is synchronous and uses blocking I/O. Running in `asyncio.to_thread()` works but adds thread pool overhead.
|
|
208
|
+
- **Mitigation**: Auth happens infrequently (once at startup, then token refresh). The overhead is negligible for this use case.
|
|
209
|
+
- **Binary protocol fidelity**: Refactoring the wire protocol encoding/decoding could introduce subtle byte-level bugs.
|
|
210
|
+
- **Mitigation**: Create comprehensive round-trip tests using known-good encoded values from the existing script before refactoring.
|
|
211
|
+
- **aiohttp session lifecycle**: Mismanaged sessions can leak connections.
|
|
212
|
+
- **Mitigation**: Use async context manager pattern consistently; provide both session injection and auto-creation.
|
|
213
|
+
</details>
|
|
214
|
+
|
|
215
|
+
<details>
|
|
216
|
+
<summary>Implementation Risks</summary>
|
|
217
|
+
|
|
218
|
+
- **Scope of refactoring**: Transforming a working script into a packaged library touches every line of code.
|
|
219
|
+
- **Mitigation**: Extract and test the wire protocol first (it's the most delicate part), then build the client around tested primitives.
|
|
220
|
+
- **textual API stability**: textual is actively developed and APIs may change.
|
|
221
|
+
- **Mitigation**: Pin textual version in dependencies; keep TUI as a separate module that can be updated independently.
|
|
222
|
+
</details>
|
|
223
|
+
|
|
224
|
+
<details>
|
|
225
|
+
<summary>Integration Risks</summary>
|
|
226
|
+
|
|
227
|
+
- **PyPI name availability**: ~~Resolved~~ — `flameconnect` is confirmed available on PyPI as of 2026-02-23.
|
|
228
|
+
- **Azure AD B2C token format changes**: The upstream auth API could change.
|
|
229
|
+
- **Mitigation**: The auth module is isolated; changes only affect `auth.py` and its tests.
|
|
230
|
+
</details>
|
|
231
|
+
|
|
232
|
+
<details>
|
|
233
|
+
<summary>Quality Risks</summary>
|
|
234
|
+
|
|
235
|
+
- **Incomplete wire protocol in existing code**: The current `decode_parameter` function handles parameters 236, 321–327, and 329, but the display functions for Sound (369) and Log Effect (370) reference keys that are never populated by the decoder. These decoders and encoders must be completed during refactoring, not just ported.
|
|
236
|
+
- **Mitigation**: Use the `FLAMECONNECT_API_REPORT.md` wire format documentation to implement complete encode/decode for all parameter types. Round-trip tests will verify correctness.
|
|
237
|
+
- **mutmut CI time**: Mutation testing can be slow on larger codebases.
|
|
238
|
+
- **Mitigation**: Start with mutmut on the focused protocol and models modules. Expand coverage as the codebase grows. Consider parallelizing mutation runs in CI.
|
|
239
|
+
</details>
|
|
240
|
+
|
|
241
|
+
## Success Criteria
|
|
242
|
+
|
|
243
|
+
### Primary Success Criteria
|
|
244
|
+
1. `flameconnect` is installable via `pip install flameconnect` (or `uv add flameconnect`) from PyPI
|
|
245
|
+
2. The async library can discover fireplaces, read state, and control parameters (on/off, flame effect, heat, timer)
|
|
246
|
+
3. `flameconnect list`, `flameconnect status`, `flameconnect on/off`, and `flameconnect set` CLI commands work correctly
|
|
247
|
+
4. `flameconnect tui` launches an interactive terminal dashboard with live fireplace status and controls
|
|
248
|
+
5. mypy strict mode passes with zero errors
|
|
249
|
+
6. ruff lint and format checks pass with zero warnings
|
|
250
|
+
7. pytest achieves high test coverage with all tests passing using fixtures (no live API calls)
|
|
251
|
+
8. mutmut mutation testing demonstrates meaningful test coverage (mutants are caught)
|
|
252
|
+
9. GitHub Actions CI runs linting, type checking, and tests on every push/PR
|
|
253
|
+
10. Conventional commits are validated in CI
|
|
254
|
+
11. release-please automates versioning and PyPI publishing on merge to main
|
|
255
|
+
12. README is written for humans with clear installation, usage examples, and API coverage documentation
|
|
256
|
+
|
|
257
|
+
## Resource Requirements
|
|
258
|
+
|
|
259
|
+
### Development Skills
|
|
260
|
+
- Python async programming (aiohttp, asyncio)
|
|
261
|
+
- Python packaging (pyproject.toml, src layout, uv)
|
|
262
|
+
- Azure AD B2C authentication (msal)
|
|
263
|
+
- Binary protocol handling (struct, base64)
|
|
264
|
+
- Terminal UI development (textual)
|
|
265
|
+
- GitHub Actions CI/CD
|
|
266
|
+
- Type system (mypy strict mode)
|
|
267
|
+
|
|
268
|
+
### Technical Infrastructure
|
|
269
|
+
- **Python 3.13+**: Required runtime
|
|
270
|
+
- **uv**: Dependency management and virtual environment
|
|
271
|
+
- **ruff**: Linting and formatting
|
|
272
|
+
- **mypy**: Static type checking
|
|
273
|
+
- **pytest + pytest-aiohttp**: Test framework
|
|
274
|
+
- **mutmut**: Mutation testing
|
|
275
|
+
- **textual**: TUI framework
|
|
276
|
+
- **aiohttp**: Async HTTP client
|
|
277
|
+
- **msal**: Azure AD B2C authentication
|
|
278
|
+
- **GitHub Actions**: CI/CD platform
|
|
279
|
+
- **release-please**: Automated release management
|
|
280
|
+
- **PyPI**: Package distribution
|
|
281
|
+
|
|
282
|
+
## Integration Strategy
|
|
283
|
+
|
|
284
|
+
The library is designed as a standalone package that can be consumed by:
|
|
285
|
+
1. **Direct users**: Via the CLI and TUI for personal fireplace control
|
|
286
|
+
2. **Home Assistant**: Via token injection into the async client (HA passes its own aiohttp session and access token)
|
|
287
|
+
3. **Other integrations**: Any Python async application can use the library's public API
|
|
288
|
+
|
|
289
|
+
The token injection pattern ensures the library doesn't impose authentication decisions on consumers. The async-first design means no `executor` wrapping is needed in Home Assistant.
|
|
290
|
+
|
|
291
|
+
## Notes
|
|
292
|
+
|
|
293
|
+
- The existing `flameconnect_reader.py` will be preserved as a reference during development and can be removed once the library is feature-complete
|
|
294
|
+
- The `FLAMECONNECT_API_REPORT.md` serves as the canonical API reference and should be kept up to date
|
|
295
|
+
- The `decomp/` directory contains reverse-engineering artifacts and is gitignored; it stays as reference material
|
|
296
|
+
- Only three core control endpoints are in scope: **GetFires** (list fireplaces), **GetFireOverview** (read state and parameters), and **WriteWifiParameters** (send control commands). There is no separate `ReadWifiParameters` endpoint — all parameter reading is done via `GetFireOverview`. Additional endpoints documented in the API report can be added incrementally in future plans.
|
|
297
|
+
- The README should clearly document which endpoints are implemented and which are available for future contribution
|
|
298
|
+
- Initial PyPI release version: **0.1.0**
|
|
299
|
+
|
|
300
|
+
## Task Dependency Graph
|
|
301
|
+
|
|
302
|
+
```mermaid
|
|
303
|
+
graph TD
|
|
304
|
+
T01[Task 01: Project Scaffolding] --> T02[Task 02: Models/Constants/Exceptions]
|
|
305
|
+
T02 --> T03[Task 03: Wire Protocol]
|
|
306
|
+
T02 --> T04[Task 04: Auth Module]
|
|
307
|
+
T03 --> T05[Task 05: Async Client]
|
|
308
|
+
T04 --> T05
|
|
309
|
+
T05 --> T06[Task 06: Tests]
|
|
310
|
+
T05 --> T07[Task 07: CLI Tool]
|
|
311
|
+
T05 --> T08[Task 08: TUI Dashboard]
|
|
312
|
+
T06 --> T09[Task 09: CI/CD Workflows]
|
|
313
|
+
T07 --> T10[Task 10: README]
|
|
314
|
+
T08 --> T10
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## Execution Blueprint
|
|
318
|
+
|
|
319
|
+
**Validation Gates:**
|
|
320
|
+
- Reference: `/config/hooks/POST_PHASE.md`
|
|
321
|
+
|
|
322
|
+
### ✅ Phase 1: Project Foundation
|
|
323
|
+
**Parallel Tasks:**
|
|
324
|
+
- ✔️ Task 01: Initialize project scaffolding with uv and configure tooling
|
|
325
|
+
|
|
326
|
+
### ✅ Phase 2: Core Types
|
|
327
|
+
**Parallel Tasks:**
|
|
328
|
+
- ✔️ Task 02: Implement models, enums, constants, and exceptions (depends on: 01)
|
|
329
|
+
|
|
330
|
+
### ✅ Phase 3: Core Modules
|
|
331
|
+
**Parallel Tasks:**
|
|
332
|
+
- ✔️ Task 03: Implement binary wire protocol encoding and decoding (depends on: 02)
|
|
333
|
+
- ✔️ Task 04: Implement authentication module with token injection and MSAL (depends on: 02)
|
|
334
|
+
|
|
335
|
+
### ✅ Phase 4: API Client
|
|
336
|
+
**Parallel Tasks:**
|
|
337
|
+
- ✔️ Task 05: Implement async API client (depends on: 03, 04)
|
|
338
|
+
|
|
339
|
+
### ✅ Phase 5: Interfaces and Testing
|
|
340
|
+
**Parallel Tasks:**
|
|
341
|
+
- ✔️ Task 06: Implement tests for protocol, client, and auth modules (depends on: 05)
|
|
342
|
+
- ✔️ Task 07: Implement CLI tool with argparse (depends on: 05)
|
|
343
|
+
- ✔️ Task 08: Implement textual TUI dashboard (depends on: 05)
|
|
344
|
+
|
|
345
|
+
### ✅ Phase 6: Infrastructure and Documentation
|
|
346
|
+
**Parallel Tasks:**
|
|
347
|
+
- ✔️ Task 09: Set up GitHub Actions CI/CD workflows (depends on: 06)
|
|
348
|
+
- ✔️ Task 10: Write human-oriented README (depends on: 07, 08)
|
|
349
|
+
|
|
350
|
+
### Execution Summary
|
|
351
|
+
- Total Phases: 6
|
|
352
|
+
- Total Tasks: 10
|
|
353
|
+
- Maximum Parallelism: 3 tasks (in Phase 5)
|
|
354
|
+
- Critical Path Length: 6 phases (01 → 02 → 03 → 05 → 06 → 09)
|
|
355
|
+
|
|
356
|
+
### Refinement Changelog
|
|
357
|
+
|
|
358
|
+
- 2026-02-23: Corrected API endpoint list — removed non-existent `ReadWifiParameters` endpoint (reading is via `GetFireOverview`)
|
|
359
|
+
- 2026-02-23: Fixed architecture diagram dependency direction (protocol depends on models, not vice versa)
|
|
360
|
+
- 2026-02-23: Added `__main__.py` and `py.typed` marker to package structure
|
|
361
|
+
- 2026-02-23: Resolved CLI framework as `argparse` (removed "or click-minimal" ambiguity)
|
|
362
|
+
- 2026-02-23: Specified textual as optional packaging extra (`flameconnect[tui]`)
|
|
363
|
+
- 2026-02-23: Confirmed `flameconnect` name available on PyPI, removed from risk list
|
|
364
|
+
- 2026-02-23: Added quality risk about incomplete Sound/Log Effect wire protocol decoders in existing code
|
|
365
|
+
- 2026-02-23: Clarified mutmut runs in main CI pipeline per user preference
|
|
366
|
+
- 2026-02-23: Added initial version 0.1.0 specification
|
|
367
|
+
- 2026-02-23: Added live API testing policy — live calls permitted during development with explain/confirm/verify protocol; CI tests remain fixture-only
|
|
368
|
+
|
|
369
|
+
## Execution Summary
|
|
370
|
+
|
|
371
|
+
**Status**: Completed Successfully
|
|
372
|
+
**Completed Date**: 2026-02-23
|
|
373
|
+
|
|
374
|
+
### Results
|
|
375
|
+
All 10 tasks across 6 phases completed successfully. The flameconnect library is now a fully packaged, async-first Python library:
|
|
376
|
+
|
|
377
|
+
- **13 source files** in `src/flameconnect/` (including 4 TUI files)
|
|
378
|
+
- **91 tests** passing across 4 test files (protocol, client, auth, models)
|
|
379
|
+
- **All quality gates pass**: ruff check, ruff format, mypy --strict (0 errors)
|
|
380
|
+
- **6 commits** on `project-foundation` branch following conventional commit format
|
|
381
|
+
|
|
382
|
+
Key deliverables:
|
|
383
|
+
- Wire protocol with complete encode/decode for all 10 parameter types
|
|
384
|
+
- Async API client with typed methods and context manager pattern
|
|
385
|
+
- Dual auth: MSAL interactive flow + token injection for HA
|
|
386
|
+
- CLI with list/status/on/off/set/tui commands
|
|
387
|
+
- Textual TUI dashboard with auto-refresh and power toggle
|
|
388
|
+
- GitHub Actions CI/CD with mutation testing, conventional commits, and release-please
|
|
389
|
+
|
|
390
|
+
### Noteworthy Events
|
|
391
|
+
- **Protocol bug fix**: The test agent discovered that `_encode_heat_settings` was missing a trailing padding byte, producing 9-byte output instead of the required 10 bytes. Fixed by adding a padding byte to match the wire format.
|
|
392
|
+
- **`fs-extra` npm dependency**: The task dependency checking script required `fs-extra` which was not initially installed. Fixed with `npm install`.
|
|
393
|
+
- **ruff exclusion for reference script**: `flameconnect_reader.py` (the original script) failed ruff linting. Added it to `[tool.ruff] exclude` rather than modifying the reference.
|
|
394
|
+
- **No live API validation performed**: All tasks completed with static analysis and fixture-based tests only. Live validation was deferred to user testing.
|
|
395
|
+
|
|
396
|
+
### Recommendations
|
|
397
|
+
1. Run `flameconnect list` and `flameconnect status` against the live API to validate end-to-end before publishing
|
|
398
|
+
2. Configure PyPI trusted publishing and GitHub `pypi` environment before the first release
|
|
399
|
+
3. Replace `USERNAME` placeholder in README badges with the actual GitHub username
|
|
400
|
+
4. Consider adding `test_cli.py` for CLI argument parsing tests in a future iteration
|
|
401
|
+
5. Run `mutmut` locally to verify mutation test results before merging
|
flameconnect-0.1.0/.ai/task-manager/archive/01--project-foundation/tasks/01--project-scaffolding.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: 1
|
|
3
|
+
group: "packaging"
|
|
4
|
+
dependencies: []
|
|
5
|
+
status: "completed"
|
|
6
|
+
created: "2026-02-23"
|
|
7
|
+
skills:
|
|
8
|
+
- python
|
|
9
|
+
- packaging
|
|
10
|
+
status: "completed"
|
|
11
|
+
status: "completed"
|
|
12
|
+
---
|
|
13
|
+
# Initialize project scaffolding with uv and configure tooling
|
|
14
|
+
|
|
15
|
+
## Objective
|
|
16
|
+
Create the Python package skeleton with `src/` layout, configure `pyproject.toml` with all dependencies and tool settings (ruff, mypy, pytest, mutmut), and initialize the uv project. This is the foundation all other tasks build on.
|
|
17
|
+
|
|
18
|
+
## Skills Required
|
|
19
|
+
- Python packaging (pyproject.toml, src layout, PEP 621)
|
|
20
|
+
- uv dependency manager
|
|
21
|
+
|
|
22
|
+
## Acceptance Criteria
|
|
23
|
+
- [ ] `pyproject.toml` exists with project metadata (name=flameconnect, version=0.1.0, python>=3.13)
|
|
24
|
+
- [ ] `src/flameconnect/__init__.py` exists with package version
|
|
25
|
+
- [ ] `src/flameconnect/__main__.py` exists (delegates to CLI)
|
|
26
|
+
- [ ] `src/flameconnect/py.typed` marker file exists (empty file)
|
|
27
|
+
- [ ] Dependencies declared: aiohttp, msal (runtime); ruff, mypy, pytest, pytest-aiohttp, mutmut (dev)
|
|
28
|
+
- [ ] Optional dependency group `tui` with textual
|
|
29
|
+
- [ ] `[project.scripts]` entry: `flameconnect = "flameconnect.cli:main"`
|
|
30
|
+
- [ ] ruff config in pyproject.toml (line-length=88, target-version="py313")
|
|
31
|
+
- [ ] mypy config in pyproject.toml (strict=true)
|
|
32
|
+
- [ ] pytest config in pyproject.toml
|
|
33
|
+
- [ ] `uv sync` succeeds and installs all dependencies
|
|
34
|
+
- [ ] `tests/` directory with empty `conftest.py` and `__init__.py`
|
|
35
|
+
- [ ] `.gitignore` updated for uv (.venv, dist, *.egg-info, .mypy_cache, .ruff_cache, .pytest_cache, .mutmut-cache)
|
|
36
|
+
|
|
37
|
+
Use your internal Todo tool to track these and keep on track.
|
|
38
|
+
|
|
39
|
+
## Technical Requirements
|
|
40
|
+
- Use PEP 621 `[project]` table in pyproject.toml (not legacy setup.py/setup.cfg)
|
|
41
|
+
- Use `[build-system]` with hatchling as build backend (standard for uv)
|
|
42
|
+
- `src/` layout: `[tool.hatch.build.targets.wheel] packages = ["src/flameconnect"]`
|
|
43
|
+
- Python requires-python = ">=3.13"
|
|
44
|
+
- Initial version: "0.1.0"
|
|
45
|
+
|
|
46
|
+
## Input Dependencies
|
|
47
|
+
None — this is the first task.
|
|
48
|
+
|
|
49
|
+
## Output Artifacts
|
|
50
|
+
- `pyproject.toml` — complete project configuration
|
|
51
|
+
- `src/flameconnect/__init__.py`, `__main__.py`, `py.typed`
|
|
52
|
+
- `tests/conftest.py`, `tests/__init__.py`
|
|
53
|
+
- `.venv/` created by uv
|
|
54
|
+
- Updated `.gitignore`
|
|
55
|
+
|
|
56
|
+
## Implementation Notes
|
|
57
|
+
|
|
58
|
+
<details>
|
|
59
|
+
<summary>Detailed implementation guidance</summary>
|
|
60
|
+
|
|
61
|
+
1. **Initialize the project**: Run `uv init` if not already initialized, or manually create `pyproject.toml`. The project is already a git repo.
|
|
62
|
+
|
|
63
|
+
2. **pyproject.toml structure**:
|
|
64
|
+
```toml
|
|
65
|
+
[build-system]
|
|
66
|
+
requires = ["hatchling"]
|
|
67
|
+
build-backend = "hatchling.build"
|
|
68
|
+
|
|
69
|
+
[project]
|
|
70
|
+
name = "flameconnect"
|
|
71
|
+
version = "0.1.0"
|
|
72
|
+
description = "Async Python library for controlling Dimplex/Faber fireplaces via the Flame Connect cloud API"
|
|
73
|
+
readme = "README.md"
|
|
74
|
+
license = "MIT"
|
|
75
|
+
requires-python = ">=3.13"
|
|
76
|
+
dependencies = [
|
|
77
|
+
"aiohttp>=3.9",
|
|
78
|
+
"msal>=1.28",
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
[project.optional-dependencies]
|
|
82
|
+
tui = ["textual>=0.50"]
|
|
83
|
+
dev = [
|
|
84
|
+
"ruff>=0.4",
|
|
85
|
+
"mypy>=1.10",
|
|
86
|
+
"pytest>=8.0",
|
|
87
|
+
"pytest-aiohttp>=1.0",
|
|
88
|
+
"pytest-asyncio>=0.23",
|
|
89
|
+
"mutmut>=2.4",
|
|
90
|
+
"aioresponses>=0.7",
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
[project.scripts]
|
|
94
|
+
flameconnect = "flameconnect.cli:main"
|
|
95
|
+
|
|
96
|
+
[tool.hatch.build.targets.wheel]
|
|
97
|
+
packages = ["src/flameconnect"]
|
|
98
|
+
|
|
99
|
+
[tool.ruff]
|
|
100
|
+
line-length = 88
|
|
101
|
+
target-version = "py313"
|
|
102
|
+
|
|
103
|
+
[tool.ruff.lint]
|
|
104
|
+
select = ["E", "F", "W", "I", "UP", "B", "SIM", "TCH"]
|
|
105
|
+
|
|
106
|
+
[tool.mypy]
|
|
107
|
+
strict = true
|
|
108
|
+
|
|
109
|
+
[tool.pytest.ini_options]
|
|
110
|
+
asyncio_mode = "auto"
|
|
111
|
+
testpaths = ["tests"]
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
3. **Create directory structure**:
|
|
115
|
+
- `src/flameconnect/__init__.py` — export `__version__ = "0.1.0"`
|
|
116
|
+
- `src/flameconnect/__main__.py` — `from flameconnect.cli import main; main()`
|
|
117
|
+
- `src/flameconnect/py.typed` — empty file
|
|
118
|
+
- `tests/__init__.py` — empty
|
|
119
|
+
- `tests/conftest.py` — empty (will be populated by test tasks)
|
|
120
|
+
|
|
121
|
+
4. **Update .gitignore**: Add uv/Python packaging entries (`.venv/`, `dist/`, `*.egg-info/`, `.mypy_cache/`, `.ruff_cache/`, `.pytest_cache/`, `.mutmut-cache/`)
|
|
122
|
+
|
|
123
|
+
5. **Run `uv sync`** to create the virtual environment and install all dependencies.
|
|
124
|
+
|
|
125
|
+
6. **Important**: `src/flameconnect/cli.py` does not need to exist yet — just ensure the entry point in pyproject.toml points to the correct location for when it's created in task 7.
|
|
126
|
+
</details>
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: 2
|
|
3
|
+
group: "core-library"
|
|
4
|
+
dependencies: [1]
|
|
5
|
+
status: "completed"
|
|
6
|
+
created: "2026-02-23"
|
|
7
|
+
skills:
|
|
8
|
+
- python
|
|
9
|
+
status: "completed"
|
|
10
|
+
status: "completed"
|
|
11
|
+
---
|
|
12
|
+
# Implement models, enums, constants, and exceptions
|
|
13
|
+
|
|
14
|
+
## Objective
|
|
15
|
+
Create the typed foundation of the library: Python `Enum` classes for all parameter values, `dataclass` types for API responses and parameter structures, constants for API configuration, and a custom exception hierarchy. These are the building blocks consumed by all other modules.
|
|
16
|
+
|
|
17
|
+
## Skills Required
|
|
18
|
+
- Python type system (dataclasses, Enum, type annotations)
|
|
19
|
+
|
|
20
|
+
## Acceptance Criteria
|
|
21
|
+
- [ ] `src/flameconnect/const.py` — API base URL, client ID, authority, scopes, default headers, ParameterId constants
|
|
22
|
+
- [ ] `src/flameconnect/models.py` — All enums (FireMode, FlameEffect, HeatStatus, HeatMode, HeatControl, FlameColor, LightStatus, TimerStatus, TempUnit, LogEffect, MediaTheme, ConnectionState) and dataclasses (Fire, FireOverview, ModeParam, FlameEffectParam, HeatParam, HeatModeParam, TimerParam, SoftwareVersionParam, ErrorParam, TempUnitParam, SoundParam, LogEffectParam)
|
|
23
|
+
- [ ] `src/flameconnect/exceptions.py` — FlameConnectError base, AuthenticationError, ApiError, ProtocolError
|
|
24
|
+
- [ ] All files pass `mypy --strict` with zero errors
|
|
25
|
+
- [ ] All files pass `ruff check` and `ruff format --check` with zero errors
|
|
26
|
+
|
|
27
|
+
Use your internal Todo tool to track these and keep on track.
|
|
28
|
+
|
|
29
|
+
## Technical Requirements
|
|
30
|
+
- Use `@dataclass(frozen=True, slots=True)` for immutable parameter types
|
|
31
|
+
- Use `IntEnum` for enums that map to wire protocol integer values
|
|
32
|
+
- Dataclasses must have full type annotations (no `Any` types)
|
|
33
|
+
- Temperature fields should be `float` type
|
|
34
|
+
- RGBW color fields should use a nested `RGBWColor` dataclass with `red`, `green`, `blue`, `white` as `int` fields
|
|
35
|
+
|
|
36
|
+
## Input Dependencies
|
|
37
|
+
- Task 1: Package skeleton must exist (`src/flameconnect/` directory, `pyproject.toml`)
|
|
38
|
+
|
|
39
|
+
## Output Artifacts
|
|
40
|
+
- `src/flameconnect/const.py`
|
|
41
|
+
- `src/flameconnect/models.py`
|
|
42
|
+
- `src/flameconnect/exceptions.py`
|
|
43
|
+
|
|
44
|
+
## Implementation Notes
|
|
45
|
+
|
|
46
|
+
<details>
|
|
47
|
+
<summary>Detailed implementation guidance</summary>
|
|
48
|
+
|
|
49
|
+
1. **const.py**: Extract all constants from `flameconnect_reader.py`:
|
|
50
|
+
```python
|
|
51
|
+
API_BASE = "https://mobileapi.gdhv-iot.com"
|
|
52
|
+
CLIENT_ID = "1af761dc-085a-411f-9cb9-53e5e2115bd2"
|
|
53
|
+
AUTHORITY = "https://gdhvb2cflameconnect.b2clogin.com/gdhvb2cflameconnect.onmicrosoft.com/B2C_1A_FirePhoneSignUpOrSignInWithPhoneOrEmail"
|
|
54
|
+
SCOPES = ["https://gdhvb2cflameconnect.onmicrosoft.com/Mobile/read"]
|
|
55
|
+
```
|
|
56
|
+
Include default HTTP headers (app_name, api_version, app_version, etc.) as a dict constant.
|
|
57
|
+
Include `ParameterId` constants as an `IntEnum` or module-level constants:
|
|
58
|
+
- TEMPERATURE_UNIT = 236, MODE = 321, FLAME_EFFECT = 322, HEAT_SETTINGS = 323, HEAT_MODE = 325, TIMER = 326, SOFTWARE_VERSION = 327, ERROR = 329, SOUND = 369, LOG_EFFECT = 370
|
|
59
|
+
|
|
60
|
+
2. **models.py**: Reference `flameconnect_reader.py` lines 33-59 for existing enum mappings. Convert each dict to a proper `IntEnum`:
|
|
61
|
+
```python
|
|
62
|
+
class FireMode(IntEnum):
|
|
63
|
+
STANDBY = 0
|
|
64
|
+
MANUAL = 1
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
For parameter dataclasses, reference the `decode_parameter` function (lines 224-283) and `FLAMECONNECT_API_REPORT.md` parameter reference section. Each decoded parameter type gets its own dataclass.
|
|
68
|
+
|
|
69
|
+
The `Fire` dataclass represents a fireplace from the GetFires response:
|
|
70
|
+
```python
|
|
71
|
+
@dataclass(frozen=True, slots=True)
|
|
72
|
+
class Fire:
|
|
73
|
+
fire_id: str
|
|
74
|
+
friendly_name: str
|
|
75
|
+
brand: str
|
|
76
|
+
product_type: str
|
|
77
|
+
product_model: str
|
|
78
|
+
item_code: str
|
|
79
|
+
connection_state: ConnectionState
|
|
80
|
+
with_heat: bool
|
|
81
|
+
is_iot_fire: bool
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Create a `RGBWColor` dataclass reused in FlameEffectParam and LogEffectParam:
|
|
85
|
+
```python
|
|
86
|
+
@dataclass(frozen=True, slots=True)
|
|
87
|
+
class RGBWColor:
|
|
88
|
+
red: int
|
|
89
|
+
green: int
|
|
90
|
+
blue: int
|
|
91
|
+
white: int
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The `FlameEffectParam` dataclass should include media_theme (RGBWColor + theme + light), overhead_light (RGBWColor + light), flame fields, etc. Reference lines 234-248 of flameconnect_reader.py.
|
|
95
|
+
|
|
96
|
+
3. **exceptions.py**: Simple hierarchy:
|
|
97
|
+
```python
|
|
98
|
+
class FlameConnectError(Exception): ...
|
|
99
|
+
class AuthenticationError(FlameConnectError): ...
|
|
100
|
+
class ApiError(FlameConnectError):
|
|
101
|
+
def __init__(self, status: int, message: str) -> None: ...
|
|
102
|
+
class ProtocolError(FlameConnectError): ...
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
4. **Important**: Use `logging.getLogger(__name__)` in any module that needs logging. No `print()`.
|
|
106
|
+
|
|
107
|
+
5. **Update `__init__.py`**: Export the key public types (FlameConnectError, Fire, and the parameter dataclasses) from the package root.
|
|
108
|
+
</details>
|