Skip to content

feat: add battery_status property to Tile - #792

Merged
bachya merged 2 commits into
bachya:devfrom
axxonite:battery-status
Sep 23, 2026
Merged

bachya merged 2 commits into
bachya:devfrom
axxonite:battery-status

Conversation

@axxonite

@axxonite axxonite commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Describe what the PR does:

Adds a battery_status property to the Tile object, plus its as_dict() entry and
README.md documentation.

The Tile API returns a battery status on every tile detail response, but Tile defines
no property for it, so consumers cannot reach it without touching _tile_data
directly. The field is already present in this repo's own fixtures — both
tile_details_response.json and tile_details_missing_last_state_response.json carry
"battery_status": "NONE" — so no fixture changes were needed.

Observed values

Checked against a live account with six Tiles. Values are NONE, LEVEL1 and
LEVEL2, and whether a Tile reports a level at all depends on its firmware generation:

Firmware battery_status
05.04.03.0 LEVEL2
05.04.03.0 LEVEL1
40.04.10.0 NONE
42.04.10.0 NONE
43.04.10.0 NONE

Because a missing level is normal rather than an error, the property uses .get() and
is typed str | None.

On last_tile_state.battery_level

#107 asked for a battery level too. I have deliberately left it out, and wanted to
show the evidence rather than just omit it silently.

Across those same six Tiles it read exactly 0.0 on every poll, on both firmware
generations. This repo's own fixture carries 0 as well. It looks like a key Tile
populates but never writes to. Exposing it would invite consumers to build low-battery
logic on a value that is always zero — which is a worse failure than the field simply
being absent, since it reads as a flat battery.

Happy to add it in a follow-up if you would rather the library mirror the full API
surface and leave that judgement to callers.

Update: LEVEL1 is the lower state

A third battery location settles this: result.metadata, which neither the current
properties nor this PR touch.

Tile metadata.battery_state metadata.battery_replaced_at battery_status
Keys "50" 2024-11-03 LEVEL2
Wallet "40" 2024-05-31 LEVEL1
Three sealed Tiles "10" — NONE

battery_state tracks battery_status, and LEVEL1 sits below LEVEL2. That is two
data points, so I have kept the docstring descriptive rather than hard-coding a mapping.

battery_state is a modelled estimate, not a reading. The Wallet above had not reported
for 406 days, which means its cell was flat, and it still reads "40". The three
"10" values are identical across Tiles activated on different dates, and this repo's
own tile_details_response.json also carries "battery_state": "10" next to
"battery_status": "NONE". That makes 10 look like a placeholder for "no data".
battery_replaced_at is the more useful of the two. If you want them, I can open a
separate PR for the metadata fields and keep this one to what you approved.

CI: the pylint failure was R0904 (Tile went to 21 public methods against the
default limit of 20). 708d6c5 adds an inline disable on the class, following the same
pattern as API.__init__'s too-many-arguments, so the project-wide limit stays as it
is. pylint, ruff, isort, mypy and the tests all pass locally.

Does this fix a specific issue?

Fixes #107

Checklist:

  • Confirm that one or more new tests are written for the new functionality.
  • Run tests and ensure everything passes (with 100% test coverage).
  • Update README.md with any new documentation.

Verified locally on Python 3.12: 12 passed, pytile/tile.py at 100% coverage
(181/181 statements overall), ruff check clean, ruff format clean, mypy clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Qui3EQaoxiVRCBVVe9waLw

The Tile API returns a battery status on every tile detail response, but the
`Tile` object defines no property for it, so consumers cannot reach it without
touching `_tile_data` directly. This closes bachya#107.

The field is already present in this repo's own test fixtures
(`tile_details_response.json` and
`tile_details_missing_last_state_response.json` both carry
`"battery_status": "NONE"`), so no fixture changes were needed.

Observed against a live account with six Tiles: values are `NONE`, `LEVEL1`
and `LEVEL2`, and whether a Tile reports a level at all depends on its
firmware generation. The `05.x` firmware reported `LEVEL1`/`LEVEL2` while
`40.x`/`42.x`/`43.x` reported `NONE`, so a missing level is normal rather
than an error. The property uses `.get()` and is typed `str | None`
accordingly.

Note on `last_tile_state.battery_level`, also requested in bachya#107: it is
deliberately not added here. Across those same six Tiles it read exactly
`0.0` on every poll, and this repo's fixture carries `0` as well. It appears
to be a key Tile populates but never writes to, so exposing it would invite
consumers to build low-battery logic on a value that is always zero.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qui3EQaoxiVRCBVVe9waLw
@codecov

codecov Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (442a2ac) to head (708d6c5).

Additional details and impacted files
@@            Coverage Diff            @@
##               dev      #792   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            5         5           
  Lines          178       181    +3     
=========================================
+ Hits           178       181    +3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@bachya bachya left a comment •

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! Can be merged when CI is addressed.

Adding `battery_status` took `Tile` to 21 public methods, one past
pylint's default of 20, which failed the Linting & Static Analysis job.

`Tile` exposes one read-only property per API field, so its method count
tracks the API surface rather than any design problem. Silence R0904 on
the class with an inline disable, matching how `API.__init__` already
handles `too-many-arguments`, instead of loosening the limit
project-wide.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qui3EQaoxiVRCBVVe9waLw
@axxonite

Copy link
Copy Markdown
Contributor Author

Thanks for the quick review. The pylint R0904 failure is fixed in 708d6c5, and pylint, ruff, isort, mypy and the tests all pass locally. The workflows on that commit are waiting for maintainer approval to run.

@bachya
bachya merged commit ba4ed44 into bachya:dev Sep 23, 2026
10 checks passed
@axxonite
axxonite deleted the battery-status branch September 23, 2026 02:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add battery level to tile object?

2 participants