8000 Tilt Pi integration by michaelheyman · Pull Request #139726 · home-assistant/core · GitHub
[go: up one dir, main page]

Skip to content

Tilt Pi integration #139726

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 25 commits into
base: dev
Choose a base branch
from
Draft

Conversation

michaelheyman
Copy link
@michaelheyman michaelheyman commented Mar 4, 2025

Breaking change

Proposed change

Adds a new integration for Tilt Pi devices, which are devices such as Raspberry Pi or similar devices running the Tilt Pi image. The purpose of Tilt Pi is to communicate with Tilt Hydrometers, which are devices used in monitoring brewing temperature and specific gravity.

Tilt Hydrometer BLE is already a supported integration. Unfortunately for my use case, my Tilt Hydrometers are not within any Bluetooth device range, and therefore the Tilt Pi provides a bridge between the Tilt Hydrometer data and use cases that rely on that data.

With this integration, we merely have to add the host of the Tilt Pi and it will automatically create temperature and gravity entities of the Tilt Hydrometers that it finds in its range.

I have been tested this personally, to fit my use case, which replaces a lot of custom RESTful sensors that are not sustainable to configure manually in my opinion.

Here are some screenshots of the working integration:

image
image
image

One thing to note in the review is that I have created an api.py module, which does not fully adhere to this requirement on the development checklist:

All communication to external devices or services must be wrapped in an external Python library hosted on pypi.

I would argue that this is fine for the following reasons:

  1. The api implementation is there to promote re-use of existing constructs and centralize maintenance and development of API interactions
  2. This doesn't seem to require its own package since it is very niche, and I would not want to have to maintain that package outside of this very lean api module described here.

Thank you for being receptive to my first contribution.

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Deprecation (breaking change to happen in the future)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

Checklist

  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
    • (See comment in "Proposed change" section)
  • I have followed the perfect PR recommendations
  • The code has been formatted using Ruff (ruff format homeassistant tests)
  • Tests have been added to verify that the new code works.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • For the updated dependencies - a link to the changelog, or at minimum a diff between library versions is added to the PR description.

To help with the load of incoming pull requests:

Copy link
@home-assistant home-assistant bot left a comment

Choose a reason for hiding this comment

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

Hi @michaelheyman

It seems you haven't yet signed a CLA. Please do so here.

Once you do that we will be able to review and accept this pull request.

Thanks!

@michaelheyman michaelheyman marked this pull request as ready for review March 4, 2025 04:37
"data": {
"name": "Tilt Pi Friendly Name",
"host": "Tilt Pi Hostname or IP Address",
"port": "Tilt Pi Port"
Copy link
Contributor

Choose a reason for hiding this comment

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

Camel-case "TiltPi" or not? – Below you used that.

For the rest: Everything except the name must be sentence-cased in the three strings above.

Copy link
Author

Choose a reason for hiding this comment

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

Thanks for the feedback!

The official naming seems to be "Tilt Pi". I have updated the strings and other places to reflect that more clearly where it comes to the string representation bed25e0

@michaelheyman michaelheyman changed the title Tilt pi Tilt Pi integration Mar 6, 2025
@michaelheyman
Copy link
Author

I believe this is just waiting for a review, if not please let me know if something is missing.


try:
await client.get_hydrometers()
except Exception as e:
Copy link
Member

Choose a reason for hiding this comment

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

Only catch bare exceptions in the config flow, we should be specific here

Comment on lines +17 to +26
session = async_get_clientsession(hass)
client = TiltPiClient(
host=entry.data[CONF_HOST],
port=entry.data[CONF_PORT],
session=session,
)

try:
await client.get_hydrometers()
except Exception as e:
Copy link
Member

Choose a reason for hiding this comment

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

when running await coordinator.async_config_entry_first_refresh, the coordinator already tries to connect, and if it raised UpdateFailed, it will automatically raise ConfigEntryNotReady, so we can remove this here. I would also recommend to just move the client creation to the coordinator

Comment on lines 35 to 40
try:
await coordinator.async_config_entry_first_refresh()
entry.runtime_data = coordinator
except ConfigEntryNotReady:
await coordinator.async_shutdown()
raise
Copy link
Member

Choose a reason for hiding this comment

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

try except not needed

Copy link
Author

Choose a reason for hiding this comment

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

See 1965042

await coordinator.async_shutdown()
raise

hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator
Copy link
Member

Choose a reason for hiding this comment

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

you already store it in the entry runtime data

Copy link
Author

Choose a reason for hiding this comment

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

See 1965042

"""Unload a config entry."""
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
coordinator: TiltPiDataUpdateCoordinator = hass.data[DOMAIN].pop(entry.entry_id)
await coordinator.async_shutdown()
Copy link
Member

Choose a reason for hiding this comment

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

this is also already called, you can just return the first line

Copy link
Author

Choose a reason for hiding this comment

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

See 1965042

Comment on lines 6 to 13
"dependencies": [],
"documentation": "https://www.home-assistant.io/integrations/tilt_pi",
"homekit": {},
"iot_class": "local_polling",
"quality_scale": "bronze",
"requirements": [],
"ssdp": [],
"zeroconf": []
Copy link
Member

Choose a reason for hiding this comment

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

remove empty fields

Copy link
Author

Choose a reason for hiding this comment

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

Removed in d558469

@@ -0,0 +1,14 @@
{
"domain": "tilt_pi",
Copy link
Member

Choose a reason for hiding this comment

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

since we already have the BLE one, we should create a brand for this

SENSOR_TYPES: Final[list[TiltEntityDescription]] = [
TiltEntityDescription(
key=ATTR_TEMPERATURE,
name="Temperature",
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
name="Temperature",

It will now use device clas translations

Copy link
Author

Choose a reason for hiding this comment

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

Done in a86ea49

Comment on lines 47 to 49
name="Gravity",
native_unit_of_measurement="SG",
icon="mdi:water",
Copy link
Member

Choose a reason for hiding this comment

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

please use translations for this

Copy link
Author

Choose a reason for hiding this comment

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

Done in a86ea49

async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up Tilt Hydrometer sensors."""
coordinator: TiltPiDataUpdateCoordinator = config_entry.runtime_data
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
coordinator: TiltPiDataUpdateCoordinator = config_entry.runtime_data
coordinator = config_entry.runtime_data

Can be removed as it already can be inferred

Copy link
Author

Choose a reason for hiding this comment

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

See 1965042

@home-assistant home-assistant bot marked this pull request as draft April 10, 2025 15:05
@home-assistant
Copy link

Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍

Learn more about our pull request process.

@joostlek
Copy link
Member

This doesn't seem to require its own package since it is very niche, and I would not want to have to maintain that package outside of this very lean api module described here.

We do still have the rule that any device or service specific code should be packaged in its own library. It's our way of giving back to the python community and this way we make sure our codebase isn't HUGE. This way we also split concerns and make stuff like testing way easier.

@joostlek
Copy link
Member
joostlek commented Jun 2, 2025

If its ready for review again, please use the button to mark it as such

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
0