Repository navigation
Release: dev -> master - #119
github-actions[bot] wants to merge 105 commits into
Conversation
Provides architecture overview, command reference, and development guidance for AI-assisted code editing. Documents async/sync package generation, device discovery pattern, token refresh strategy, and file-based testing workflow.
merg master onto Dev
- Scan interval fixed at 2 minutes (_SCAN_INTERVAL constant); removed updateInterval() method and scan_interval config option from startSession() - Added forceUpdate() to Hive class for power users needing an immediate poll; skips with debug log if another poll is already in flight - Extracted _pollDevices() as the single internal poll call site; used by both updateData() and forceUpdate() - Removed all Hive camera code (discontinued product): camera.py, data/camera.json, getCamera(), getCameraImage/Recording API methods, camera URLs, camera param from request(), deviceList["camera"], Camera_Temp sensor command, and hivecamera PRODUCTS block - Added pytest-asyncio tests for forceUpdate() idle and locked scenarios Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ranch protection - Added dev-release-pr.yml workflow that triggers on dev branch pushes to automatically bump patch version in setup.py and create a release PR to master (skips if PR already exists or commit message contains 'chore: bump version') - Added guard-master.yml workflow that enforces PRs to master branch must originate from dev branch only - Both workflows use GitHub CLI (gh) for PR operations and configure github-actions[bot] as commit
…mic-refresh Refactor: fix scan interval at 2 min, add forceUpdate, remove camera
…mplicit (fall through) returns' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
…lease pipeline, document branching model - Removed python-package.yml (duplicated by ci.yml lint-flake8 job) - Removed release_draft.yml (superseded by automatic release notes in release-on-master.yml) - Removed dev branch trigger from ci.yml (now runs on PRs and master pushes only) - Added release-on-master.yml workflow that reads version from setup.py, creates tag vX.Y.Z and GitHub Release with auto-generated notes on master pushes (skips if tag exists) - Added docs/workflows/README.md documenting the feature
…nges - Added paths filter to master push trigger (src, tests, requirements, setup files, config files, CI workflow itself) - Added identical paths filter to pull_request trigger - Prevents unnecessary CI runs when only docs, README, or other non-code files change
Consolidate GitHub workflows and document release automation
Deletes alarm.py, alarm.json, and removes all alarm-related code from hive.py, session.py, const.py, hive_async_api.py, and hive_api.py. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Renames all camelCase instance attributes to follow Python snake_case convention: tokenData→token_data, tokenCreated→token_created, tokenExpiry→token_expiry, homeID→home_id, lastUpdate→last_update, scanInterval→scan_interval, userID→user_id, errorList→error_list, updateLock→update_lock, _refreshLock→_refresh_lock, _refreshThreshold→_refresh_threshold, _updateTask→_update_task, _lastPollSlow→_last_poll_slow, _slowPollThreshold→_slow_poll_threshold. Updated across session.py, hive.py, hive_api.py, hive_async_api.py, and hive_helper.py. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
entityCache→entity_cache, deviceList→device_list, _entityCacheKey→_entity_cache_key, getCachedDevice→get_cached_device, setCachedDevice→set_cached_device, shouldUseCachedData→should_use_cached_data. Updated across session.py, hive_helper.py, heating.py, hotwater.py, light.py, plug.py, action.py, and sensor.py. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…aclasses
- hivedataclasses.py: update Device to snake_case fields, add EntityConfig
- const.py: replace string-based PRODUCTS/DEVICES with EntityConfig instances,
remove ACTIONS constant, update sensor_commands to use attribute access
- session.py: replace eval() in createDevices with EntityConfig iteration,
update addList to return Device objects with snake_case fields,
update _entity_cache_key to use attribute access
- All device modules: replace device["hiveID"] dict access with device.hive_id
attribute access throughout (hive_id, hive_type, ha_type, hive_name, ha_name,
device_data, parent_device, is_group, device_id, device_name)
- Replace device.setdefault("status", ...) with direct attribute assignment
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes the blanket `# pylint: skip-file` from all source files and replaces it with explicit `# pylint: disable=<codes>` directives that document exactly which rules are suppressed and why: - C0103: public API method names use camelCase (HA integration constraint) - E1101: false positives from the mixin pattern (self.session injected by subclass) - R0914/R0915: complex methods that would need major refactoring to split Also fixes all pylint issues that were genuinely easy to resolve: removes unnecessary else-after-return, converts f-strings in logging calls to lazy % formatting, fixes inconsistent return statements, uses `in` for tuple membership tests, and removes an unnecessary pass statement. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The updateLock attribute was renamed to update_lock in the snake_case refactor. Update the test to match. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Converts remaining camelCase method names to Python snake_case convention: - action.py: getAction→get_action, getState→get_state, setStatusOn→set_status_on, setStatusOff→set_status_off, actionType→action_type - hive_api.py: refreshTokens→refresh_tokens, getLoginInfo→get_login_info, getAll→get_all, getDevices→get_devices, getProducts→get_products, getActions→get_actions, motionSensor→motion_sensor, getWeather→get_weather, setState
Adds camelCase wrapper methods that delegate to the new snake_case methods to maintain compatibility with existing Home Assistant integration code: - session.py: deviceList property, startSession, updateData - heating.py: setMode, setTargetTemperature, setBoostOn, setBoostOff, getClimate - hotwater.py: setMode, setBoostOn, setBoostOff, getWaterHeater - light.py: turnOn, turnOff, getLight - plug.py: turnOn, turnOff, getSwitch - sensor.
…ead of dict construction Replaces manual dict construction in get_* methods across heating.py, hotwater.py, light.py, plug.py, and sensor.py with direct Device attribute assignment. Updates set_cached_device to store and return the Device object itself rather than a separate dict. Adds dict-style access methods (__getitem__, __setitem__, __contains__, get) to Device dataclass with camelCase→snake_case key translation via
Adds special-case handling for action-type entities in addList to construct Device objects directly from the action data dict instead of calling get_device_data (which expects product/device structure). Actions now populate minimal fields (hive_id, hive_name, device_id, device_name, ha_name all set to action name/id, empty device_data, parent_device set to hub_id). Updates action.py get_action to assign status and device_data
…leaner state management - .claude/settings.json, .codex/hooks.json: add PreToolUse hooks to prompt reading GRAPH_REPORT.md before file searches - AGENTS.md, CLAUDE.md: document graphify usage rules (read GRAPH_REPORT.md first, prefer `graphify query/path/explain` over grep, run `graphify update` after code changes) - pyproject.toml: add dev dependencies including graphifyy - action.py: extract _set_action_state helper to deduplicate set
Adds graphify-out/ to exclusion patterns in .github/workflows/ci.yml (via find -not -path) and .pre-commit-config.yaml (via exclude directive) to prevent linting/formatting of generated knowledge graph artifacts. Includes initial graphify output: .graphify_python interpreter marker, GRAPH_REPORT.md with 689 nodes/1578 edges across 44 communities, and JSON cache files for extracted code entities.
…pers - hivedataclasses.py: add SessionTokens and SessionConfig dataclasses to replace Map-based tokens/config dicts - session.py: replace self.tokens/self.config Map instances with SessionTokens/SessionConfig dataclasses, update all attribute access to use dataclass fields - hive_helper.py: move epoch_time from session.py to helper module as standalone function - session.py: add _retry_with_backoff helper to deduplicate retry logic in
…eapi into tidy-up-codebase-v2
On large PRs Claude fanned the review out to background agents and ended its turn to wait for them; the Action session then exited, the agents were killed and no comment was ever posted. Disallow Agent/Task and allow git fetch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review summaryThis is a large release/aggregation PR (133 files, +22.3k/-8k) that restructures Notable security fixes in this PR (not new issues, call these out as good):
Correctness/async review: no blocking-call-in-async-context or incorrect await/async issues found in the reviewed files. Types/style: the renamed methods consistently use Tests: extensive new coverage was added ( Caveat: given the size of this PR I was not able to exhaustively review every device handler ( |
- Skip release PRs targeting master (huge aggregate diffs, ~$1.70/run) - Remove temporary show_full_output now that reviews post correctly - Rewrite prompt: prioritised checklist with project rules (unasync source, shims, HA camelCase aliases, placeholder AWS creds, PII, 99% coverage), no style nits, de-dupe earlier comments, summary format Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…egration Add HA integration source, user docs and developer docs URLs to the review prompt, and allow WebFetch for those domains only, so API changes are checked against how Home Assistant actually calls them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fork PRs get no secrets on pull_request. pull_request_target runs with secrets but bypasses the fork-approval setting, so gate it on a maintainer adding the claude-review label. PR head is fetched as data only (never checked out or executed) and checkout no longer persists credentials. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…uest_target) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fork reviews post as github-actions[bot], so every inline comment and summary now carries a 'Claude Code Review' header, and the summary ends with a link to the workflow run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ults - Add .github/CODEOWNERS so changes under .github/ need maintainer review - Pin every action to a full commit SHA (version kept in a comment for Dependabot) so a moved tag can't swap in different code - Declare contents: read in workflows that relied on the repo default, ahead of switching the default GITHUB_TOKEN to read-only Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The review blocked #153 based on #136's history, but Home Assistant has since moved to aiobotocore 3.x and pins boto3/botocore==1.42.97 in package_constraints.txt. For dependency changes, fetch HA's current constraints and requirements before judging version ranges. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ts (#153) The <1.38 ceiling was stale and started conflicting with other Home Assistant integrations (e.g. LLM Vision) that require a newer boto3 with no upper bound, causing HA's requirements installer to fail setup entirely with RequirementsNotFound for any integration that depends on this package. The AWS Cognito IdP auth calls this library relies on (InitiateAuth/RespondToAuthChallenge) are stable across boto3/botocore versions, so there's no need to cap it. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> Co-authored-by: Khole <29937485+KJonline@users.noreply.github.com>
Replace path filters with a 'changes' job. Path-filtered workflows never report their required checks (Tests (Python 3.x), Coverage), so PRs that didn't touch code sat blocked. Now the workflow always runs and: - Tests (per-version) skip their steps unless .py/src/tests changed (matrix jobs can't be skipped at job level without breaking the required check names) - Coverage (moved in from coverage.yml) skips at job level - Packaging also runs for pyproject.toml/setup.py/MANIFEST.in changes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…39 (#160) Bumps [anthropics/claude-code-action](https://github.com/anthropics/claude-code-action) from 1.0.235 to 1.0.239. - [Release notes](https://github.com/anthropics/claude-code-action/releases) - [Commits](anthropics/claude-code-action@756cc22...97c5347) --- updated-dependencies: - dependency-name: anthropics/claude-code-action dependency-version: 1.0.239 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* ci: remove Claude Code Review workflow * ci: add automatic PR review job and centralize Claude configuration Add `claude-review` job that runs on every PR (same-repo via `pull_request`, forks via labeled `pull_request_target`). Move project knowledge to `CLAUDE.md` and consolidate tool permissions in workflow `env` so both jobs (review and `@claude` mentions) share the same configuration. The review job fetches PR head as data only, never executes fork code, and posts findings as inline comments plus a summary via `gh pr comment`.
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 8.0.1 to 8.0.2. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](actions/download-artifact@3e5f45b...9000827) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: 8.0.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…47 (#163) Bumps [anthropics/claude-code-action](https://github.com/anthropics/claude-code-action) from 1.0.239 to 1.0.247. - [Release notes](https://github.com/anthropics/claude-code-action/releases) - [Commits](anthropics/claude-code-action@97c5347...2dca132) --- updated-dependencies: - dependency-name: anthropics/claude-code-action dependency-version: 1.0.247 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 7.0.1 to 7.0.2. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](actions/upload-artifact@043fb46...cf430e0) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: 7.0.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
_execute_state_change is documented to return False on failure, but a
Hive API timeout propagated as asyncio.TimeoutError, and a failed
request (for which _call_endpoint returns {}) raised KeyError on
resp["original"]. In Home Assistant this aborts the whole multi-entity
service call (e.g. climate.set_hvac_mode on several TRVs) and bypasses
continue_on_error, since neither is a HomeAssistantError.
Catch the timeout and read the status with .get() so both cases log
and return False as documented. Polling's own timeout handling is
unchanged.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Khole <29937485+KJonline@users.noreply.github.com>
…gs (#162) * refactor: handle incomplete Hive API state responses without error logs Replace try/except KeyError blocks in heating/hotwater get_mode with early returns when state.mode is missing. Add _keep_missing_state to PollingMixin that carries over dropped state keys from the previous poll for up to MAX_STALE_STATE_POLLS (5) consecutive incomplete responses, logging a warning per poll listing affected products and missing keys, plus a debug log showing the keys that did arrive. After the threshold, accept * fix: only carry over required state keys from an incomplete poll Keys Hive may legitimately omit (boost, the colour keys) were kept from the previous poll for up to five polls, which could report stale state such as boost ON. Carry over only mode, name, status and target, and drop the per-product count for products that leave the response. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* refactor: handle incomplete Hive API state responses without error logs Replace try/except KeyError blocks in heating/hotwater get_mode with early returns when state.mode is missing. Add _keep_missing_state to PollingMixin that carries over dropped state keys from the previous poll for up to MAX_STALE_STATE_POLLS (5) consecutive incomplete responses, logging a warning per poll listing affected products and missing keys, plus a debug log showing the keys that did arrive. After the threshold, accept * fix: only carry over required state keys from an incomplete poll Keys Hive may legitimately omit (boost, the colour keys) were kept from the previous poll for up to five polls, which could report stale state such as boost ON. Carry over only mode, name, status and target, and drop the per-product count for products that leave the response. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ci: add Makefile targets for local session runner and ignore logs/ Add `run-file`, `run-live`, `simulate-file`, `simulate-live` targets that start background polling sessions (fixture or real account) and write to logs/. Add `logs` (tail -F), `status` (list runners), `stop` (kill runners), and `live-forget` (clear keychain credentials). Ignore logs/ in .gitignore. * feat: add interactive admin commands to local session runner Add `make call` target and `--call` flag that send commands to a running session over a Unix socket. Commands include poll, mode/state inspection, drop control, debug/interval adjustment, and device control (set-mode, set-temp, boost, turn-on/off). Device control requires `--allow-writes` flag at session start. Add `make help` target documenting all targets and options. Refactor Makefile to use RUN_FLAGS for shared options and add detailed --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* chore: bump version to 2.0.0.B4
* fix: treat HiveInvalidDeviceAuthentication as reauth-required and handle options=None
Add HiveInvalidDeviceAuthentication to the set of exceptions that trigger
HiveReauthRequired in _retry_login, since rejected device credentials need
a fresh SMS login. Replace config.get("options", {}) with
(config.get("options") or {}) so options=None doesn't raise AttributeError.
Add tests for both cases.
* fix: round RGB channels and retry all login failures before reauth
Change int() to round() in LightColorHandler.get_color so HSV->RGB conversion rounds channels instead of truncating (2.55 -> 3, not 2). Remove retry_on parameter from _retry_with_delays since it always retried Exception anyway. Retry every login failure (network, malformed response, library errors) in _retry_login instead of only HiveApiError, converting all exhausted retries to HiveReauthRequired. Add tests for channel rounding and transient failure
Adds examples/example_login.py: password + SMS on the first run, with the machine registered as a trusted device and credentials saved to hive_device.json (owner-only, gitignored); later runs use device_login and skip SMS. Verified live: second run skipped SMS and listed the same 73 devices. Closes #68, closes #57, closes #63, closes #65, closes #109 Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Since 2026-10-20 https://sso.hivehome.com/ emits its bootstrap config as window.HiveSSOPoolId = 'eu-west-1_...' (single quotes, spaces around =) instead of window.HiveSSOPoolId="...". _SSO_ASSIGNMENT only matched double quotes, so get_login_info() raised KeyError, returned None, and HiveAuthAsync.async_init crashed with AttributeError on self.data.get. Home Assistant then fails to set up the Hive integration after a restart (home-assistant/core#187516). Accept either quote character, requiring the closing quote to match, and add unit tests for the new format and for mismatched quotes. Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> Co-authored-by: Khole <29937485+KJonline@users.noreply.github.com>
…51 (#168) Bumps [anthropics/claude-code-action](https://github.com/anthropics/claude-code-action) from 1.0.247 to 1.0.251. - [Release notes](https://github.com/anthropics/claude-code-action/releases) - [Commits](anthropics/claude-code-action@2dca132...374f254) --- updated-dependencies: - dependency-name: anthropics/claude-code-action dependency-version: 1.0.251 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…RROR (#180) * fix: log skipped discovery entities with context instead of a blank ERROR add_list caught KeyError and called _LOGGER.error(error). For a trvcontrol product with no linked TRVs, get_device_data logged its own ERROR and then raised a bare KeyError, whose str() is empty, so Home Assistant showed a second, blank ERROR entry. get_device_data now raises KeyError with a message and no longer logs, and add_list logs one WARNING naming the entity type, Hive product type and id, and the missing key. Fixes home-assistant/core#172819 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: drop local logging import now imported at module level Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Automated release PR. Contains merged feature PRs and a single version bump.