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鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add climate platform to Mazda integration #75037
Conversation
client = hass.data[DOMAIN][config_entry.entry_id][DATA_CLIENT] | ||
coordinator = hass.data[DOMAIN][config_entry.entry_id][DATA_COORDINATOR] | ||
region = hass.data[DOMAIN][config_entry.entry_id][DATA_REGION] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd probably unpack this first to reduce the number of dict lookups python has to do.
Ideally we store the data as a dataclass
instead of dict
so it has better typing
domain_data = hass.data[DOMAIN][config_entry.entry_id]
client = domain_data[DATA_CLIENT]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I have updated the code to unpack the dict first.
I agree with your dataclass
suggestion. I'm planning to open a general cleanup PR after this PR is merged, and I'll make sure to include that change. By the way, do you know of any other integrations that use a dataclass
in this way, so I can use them as an example?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lookin
has an example
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I'll refer to that when I work on the follow-up PR.
Hi @OnFreund, I've addressed your comments above. Would you mind taking another look please? Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a few minor comments, but looks good to me
@callback | ||
def _handle_coordinator_update(self) -> None: | ||
"""Update attributes when the coordinator data updates.""" | ||
self._update_state_attributes() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be pushed to MazdaEntity
? That way each platform only needs to implement _update_state_attributes()
and not have to worry about calling super()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this idea, but since it would affect several platforms, I would like to do this in a separate follow-up PR after this one is merged.
|
||
async def async_set_temperature(self, **kwargs: Any) -> None: | ||
"""Set a new target temperature.""" | ||
if (temperature := kwargs.get(ATTR_TEMPERATURE)) is not None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be cleaner if you reversed the condition and returned early so you could outdent below
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually did it this way because I couldn't find a way to achieve 100% test coverage otherwise. It doesn't seem possible to create a test scenario where kwargs.get(ATTR_TEMPERATURE)
is None
, but I need to check that case in order for the type checker to pass.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can make a service call for set_temperature
that passes low and high target temps instead of ATTR_TEMPERATURE
.
entry_data = hass.data[DOMAIN][config_entry.entry_id] | ||
client = entry_data[DATA_CLIENT] | ||
coordinator = entry_data[DATA_COORDINATOR] | ||
region = entry_data[DATA_REGION] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be a bit cleaner if entry_data was a @dataclass
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. We already discussed this previously here: #75037 (comment). I plan to implement this in a follow-up PR after this one is merged.
@bdr99 Can you take care of the unit enum? |
@bdraco Thanks for approving. The unit enums are fixed. |
There seems to be an issue where the CI checks are failing globally across all PRs right now. |
Probably wait an hour for the rate limit to clear than
and push |
@bdraco The CI checks passed now. Good idea with the empty commit, I didn't know about |
if self.data["hvacSetting"]["temperatureUnit"] == "F": | ||
self._attr_precision = PRECISION_WHOLE | ||
self._attr_temperature_unit = UnitOfTemperature.FAHRENHEIT | ||
self._attr_min_temp = 61.0 | ||
self._attr_max_temp = 83.0 | ||
else: | ||
self._attr_precision = PRECISION_HALVES | ||
self._attr_temperature_unit = UnitOfTemperature.CELSIUS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need these two cases if the API always reports the temperature data in Celsius? The climate integration will convert between C and F for all the temperature attributes based on the climate entity temperature_unit
attribute and the user globally configured temperature unit.
The idea is that the platform shouldn't need to bother with converting.
elif hvac_mode == HVACMode.OFF: | ||
await self.client.turn_off_hvac(self.vehicle_id) | ||
|
||
self._handle_coordinator_update() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit weird to call this method when there's no coordinator update. I'd create a different helper that we can call that calls self._update_state_attributes
and self.async_write_ha_state
.
Proposed change
Add a climate entity to the Mazda integration that allows controlling the vehicle's HVAC system. Only works for electric vehicles.
Type of change
Additional information
Checklist
black --fast homeassistant tests
)If user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
Updated and included derived files by running:
python3 -m script.hassfest
.requirements_all.txt
.Updated by running
python3 -m script.gen_requirements_all
..coveragerc
.The integration reached or maintains the following Integration Quality Scale:
To help with the load of incoming pull requests: