Skip to content
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

Merged
merged 15 commits into from Dec 27, 2022

Conversation

bdr99
Copy link
Contributor

@bdr99 bdr99 commented Jul 12, 2022

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

  • 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
  • The code has been formatted using Black (black --fast 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.
  • Untested files have been added to .coveragerc.

The integration reached or maintains the following Integration Quality Scale:

  • No score or internal
  • 馃 Silver
  • 馃 Gold
  • 馃弳 Platinum

To help with the load of incoming pull requests:

@project-bot project-bot bot added this to Needs review in Dev Jul 12, 2022
@project-bot project-bot bot moved this from Needs review to By Code Owner in Dev Jul 12, 2022
@frenck frenck added the smash Indicator this PR is close to finish for merging or closing label Jul 25, 2022
homeassistant/components/mazda/climate.py Outdated Show resolved Hide resolved
homeassistant/components/mazda/climate.py Outdated Show resolved Hide resolved
homeassistant/components/mazda/climate.py Outdated Show resolved Hide resolved
Comment on lines 36 to 38
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]
Copy link
Member

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]

Copy link
Contributor Author

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?

Copy link
Member

Choose a reason for hiding this comment

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

lookin has an example

Copy link
Contributor Author

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.

@bdr99 bdr99 requested a review from OnFreund September 4, 2022 01:48
@bdr99 bdr99 mentioned this pull request Sep 4, 2022
homeassistant/components/mazda/climate.py Outdated Show resolved Hide resolved
homeassistant/components/mazda/climate.py Outdated Show resolved Hide resolved
homeassistant/components/mazda/climate.py Outdated Show resolved Hide resolved
homeassistant/components/mazda/climate.py Outdated Show resolved Hide resolved
homeassistant/components/mazda/climate.py Outdated Show resolved Hide resolved
Dev automation moved this from By Code Owner to Review in progress Sep 16, 2022
@bdr99
Copy link
Contributor Author

bdr99 commented Sep 26, 2022

Hi @OnFreund, I've addressed your comments above. Would you mind taking another look please? Thanks!

@bdr99 bdr99 requested a review from OnFreund September 26, 2022 19:31
Copy link
Contributor

@OnFreund OnFreund left a 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()
Copy link
Contributor

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().

Copy link
Contributor Author

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.

homeassistant/components/mazda/climate.py Show resolved Hide resolved
homeassistant/components/mazda/climate.py Outdated Show resolved Hide resolved
@bdr99 bdr99 requested a review from bdraco November 8, 2022 21:40

async def async_set_temperature(self, **kwargs: Any) -> None:
"""Set a new target temperature."""
if (temperature := kwargs.get(ATTR_TEMPERATURE)) is not None:
Copy link
Member

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

Copy link
Contributor Author

@bdr99 bdr99 Dec 27, 2022

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.

Copy link
Member

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.

Comment on lines +55 to +58
entry_data = hass.data[DOMAIN][config_entry.entry_id]
client = entry_data[DATA_CLIENT]
coordinator = entry_data[DATA_COORDINATOR]
region = entry_data[DATA_REGION]
Copy link
Member

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

Copy link
Contributor Author

@bdr99 bdr99 Dec 27, 2022

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.

Dev automation moved this from Review in progress to Reviewer approved Dec 27, 2022
@bdraco
Copy link
Member

bdraco commented Dec 27, 2022

@bdr99 Can you take care of the unit enum?

@bdr99
Copy link
Contributor Author

bdr99 commented Dec 27, 2022

@bdraco Thanks for approving. The unit enums are fixed.

@bdr99
Copy link
Contributor Author

bdr99 commented Dec 27, 2022

There seems to be an issue where the CI checks are failing globally across all PRs right now.

@bdraco
Copy link
Member

bdraco commented Dec 27, 2022

Probably wait an hour for the rate limit to clear than

git commit -m 'empty' -n --allow-empty

and push

@bdr99
Copy link
Contributor Author

bdr99 commented Dec 27, 2022

@bdraco The CI checks passed now. Good idea with the empty commit, I didn't know about --allow-empty.

@bdraco bdraco merged commit f5c5615 into home-assistant:dev Dec 27, 2022
Dev automation moved this from Reviewer approved to Done Dec 27, 2022
@github-actions github-actions bot locked and limited conversation to collaborators Dec 28, 2022
Comment on lines +94 to +101
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
Copy link
Member

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()
Copy link
Member

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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
Dev
  
Done
Development

Successfully merging this pull request may close these issues.

None yet

7 participants