Repository navigation
Release: dev -> master - #119
Open
github-actions[bot] wants to merge 116 commits into
Open
github-actions[bot] wants to merge 116 commits into
github-actions[bot] wants to merge 116 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
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>
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 7.0.0 to 7.1.0. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](actions/setup-python@5fda3b9...6d4fd22) --- updated-dependencies: - dependency-name: actions/setup-python dependency-version: 7.1.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…59 (#184) Bumps [anthropics/claude-code-action](https://github.com/anthropics/claude-code-action) from 1.0.251 to 1.0.259. - [Release notes](https://github.com/anthropics/claude-code-action/releases) - [Commits](anthropics/claude-code-action@374f254...ae68417) --- updated-dependencies: - dependency-name: anthropics/claude-code-action dependency-version: 1.0.259 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> Co-authored-by: Khole <29937485+KJonline@users.noreply.github.com>
…183) Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.14.2 to 1.14.3. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](pypa/gh-action-pypi-publish@dc37677...7245906) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-version: 1.14.3 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> Co-authored-by: Khole <29937485+KJonline@users.noreply.github.com>
…64 (#186) Bumps [anthropics/claude-code-action](https://github.com/anthropics/claude-code-action) from 1.0.259 to 1.0.264. - [Release notes](https://github.com/anthropics/claude-code-action/releases) - [Commits](anthropics/claude-code-action@ae68417...d70510b) --- updated-dependencies: - dependency-name: anthropics/claude-code-action dependency-version: 1.0.264 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>
The sense product in src/data/data.json referenced a parent ID no device had, so file-mode sessions logged a KeyError for each sense entity and silently dropped the Glass, Smoke and Dog Bark binary sensors. Point it at the fixture hub and add a regression test that asserts a file-mode start_session logs no errors and discovers all three sense sensors. Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Hive's Cognito pool treats the email as case-sensitive, so a capitalised address (for example from mobile autocapitalisation) fails with HiveInvalidPassword even though the account exists. Store the username trimmed and lower-cased via a property on both auth classes, so the constructor and start_session's reassignment from the Home Assistant config entry are both covered. Fixes home-assistant/core#185593 Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Khole <29937485+KJonline@users.noreply.github.com>
* feat: add thermostat temperature history
Adds get_heating_history to both API layers (async and sync), calling
/history/heating/<id> with start/end in ms since epoch, timeUnit and rate,
always with operation=AVG (the only value Hive accepts).
Adds Climate.get_temperature_history(device, start, end, time_unit, rate),
which returns [{"date": <int ms>, "temperature": <float>}, ...] sorted by
date, with int-cast dates (Hive returns them as strings). Returns [] in
file mode, on HiveApiError (Hive answers 404 for zones with no history,
including TRVs) and for malformed responses. camelCase alias
getTemperatureHistory included.
Verified live against a heating zone: 24 hourly rows over a day and 7 daily
rows over a week. TRV zones return 404 as noted in the issue.
Closes #34
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* fix: harden get_temperature_history error handling
Refresh tokens before the request, return [] on timeouts as the
docstring promised, let HiveAuthError propagate so the caller can
re-authenticate, and skip TRV zones whose history endpoint 404s.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Adds ScheduleMixin (src/devices/schedule.py), composed into HiveHeating and HiveHotwater. get_schedule returns an editable copy of the weekly schedule; set_schedule validates and normalises the week, posts all seven days (Hive only accepts full-week updates), then re-reads the product and returns False if Hive silently ignored the change. camelCase aliases getSchedule/setSchedule are included for HA compatibility. Verified live on a trvcontrol zone: slot edit stored and restored correctly. Closes #19 Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> Co-authored-by: Khole <29937485+KJonline@users.noreply.github.com>
* fix: record token_created after device login device_login() returned the AuthenticationResult without storing it, so auth.token_created stayed None and get_device_data() reported no issue time after a device login. The session then fell back to the epoch default for token_created and treated every start as an expired token (issue #123). login() and sms_2fa() already go through _store_auth_result(); device_login() now does the same. Verified live: after a device login, start_session with the four-value device_data from get_device_data() now starts with the real expiry and performs no startup refresh. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * chore: update detect-secrets baseline line numbers Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> Co-authored-by: Khole <29937485+KJonline@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automated release PR. Contains merged feature PRs and a single version bump.