-
-
Notifications
You must be signed in to change notification settings - Fork 37.8k
Convert Anova to cloud push #109508
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
Convert Anova to cloud push #109508
Changes from 24 commits
5fd7787
e10a0c3
6eafd72
eaaa018
081830e
7de5e23
24fd8d2
d407f7d
792b4ed
c216b9a
6110fc2
5a56775
74b9050
18a3adc
8fe407e
f1613bf
63498c6
5048b2f
e9207d1
82a74a9
51d1a0c
71f589f
bec5a30
b8f13c1
1135a28
c65a87b
dcf9058
c020996
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,7 +5,7 @@ | |
| from collections.abc import Callable | ||
| from dataclasses import dataclass | ||
|
|
||
| from anova_wifi import APCUpdateSensor | ||
| from anova_wifi import AnovaMode, AnovaState, APCUpdateSensor | ||
|
|
||
| from homeassistant import config_entries | ||
| from homeassistant.components.sensor import ( | ||
|
|
@@ -20,25 +20,19 @@ | |
| from homeassistant.helpers.typing import StateType | ||
|
|
||
| from .const import DOMAIN | ||
| from .coordinator import AnovaCoordinator | ||
| from .entity import AnovaDescriptionEntity | ||
| from .models import AnovaData | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class AnovaSensorEntityDescriptionMixin: | ||
| """Describes the mixin variables for anova sensors.""" | ||
|
|
||
| value_fn: Callable[[APCUpdateSensor], float | int | str] | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class AnovaSensorEntityDescription( | ||
| SensorEntityDescription, AnovaSensorEntityDescriptionMixin | ||
| ): | ||
| @dataclass(frozen=True, kw_only=True) | ||
| class AnovaSensorEntityDescription(SensorEntityDescription): | ||
| """Describes a Anova sensor.""" | ||
|
|
||
| value_fn: Callable[[APCUpdateSensor], StateType] | ||
|
|
||
| SENSOR_DESCRIPTIONS: list[SensorEntityDescription] = [ | ||
|
|
||
| SENSOR_DESCRIPTIONS: list[AnovaSensorEntityDescription] = [ | ||
| AnovaSensorEntityDescription( | ||
| key="cook_time", | ||
| state_class=SensorStateClass.TOTAL_INCREASING, | ||
|
|
@@ -50,11 +44,15 @@ class AnovaSensorEntityDescription( | |
| AnovaSensorEntityDescription( | ||
| key="state", | ||
| translation_key="state", | ||
| device_class=SensorDeviceClass.ENUM, | ||
| options=[state.name for state in AnovaState], | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What should we do in the case of "no_state"?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That should be fine I think. "no_state" should get turned into "No state" through translations. It's why I use name instead of value. I create the stateby doing AnovaState(response_from_api) - when state is "" - it sets state = AnovaState.no_state Then the value is saved to AnovaUpdateSensor as the state.name
Lash-L marked this conversation as resolved.
|
||
| value_fn=lambda data: data.state, | ||
| ), | ||
| AnovaSensorEntityDescription( | ||
| key="mode", | ||
| translation_key="mode", | ||
| device_class=SensorDeviceClass.ENUM, | ||
| options=[mode.name for mode in AnovaMode], | ||
| value_fn=lambda data: data.mode, | ||
|
Lash-L marked this conversation as resolved.
|
||
| ), | ||
| AnovaSensorEntityDescription( | ||
|
|
@@ -106,11 +104,34 @@ async def async_setup_entry( | |
| ) -> None: | ||
| """Set up Anova device.""" | ||
| anova_data: AnovaData = hass.data[DOMAIN][entry.entry_id] | ||
| async_add_entities( | ||
| AnovaSensor(coordinator, description) | ||
| for coordinator in anova_data.coordinators | ||
| for description in SENSOR_DESCRIPTIONS | ||
| ) | ||
|
|
||
| for coordinator in anova_data.coordinators: | ||
| setup_coordinator(coordinator, async_add_entities) | ||
|
|
||
|
|
||
| def setup_coordinator( | ||
| coordinator: AnovaCoordinator, | ||
| async_add_entities: AddEntitiesCallback, | ||
| ) -> None: | ||
| """Set up an individual Anova Coordinator.""" | ||
|
|
||
| def _async_sensor_listener() -> None: | ||
| """Listen for new sensor data and add sensors if they did not exist.""" | ||
| if not coordinator.sensor_data_set: | ||
| valid_entities: set[AnovaSensor] = set() | ||
| for description in SENSOR_DESCRIPTIONS: | ||
| if description.value_fn(coordinator.data.sensor) is not None: | ||
| valid_entities.add(AnovaSensor(coordinator, description)) | ||
| async_add_entities(valid_entities) | ||
| coordinator.sensor_data_set = True | ||
|
|
||
| if coordinator.data is not None: | ||
| _async_sensor_listener() | ||
| # It is possible that we don't have any data, but the device exists, | ||
| # i.e. slow network, offline device, etc. | ||
| # We want to set up sensors after the fact as we don't know what sensors | ||
| # are valid until runtime. | ||
| coordinator.async_add_listener(_async_sensor_listener) | ||
|
|
||
|
|
||
| class AnovaSensor(AnovaDescriptionEntity, SensorEntity): | ||
|
|
||
This file was deleted.
Uh oh!
There was an error while loading. Please reload this page.