-
-
Notifications
You must be signed in to change notification settings - Fork 31.8k
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
Allow per-sensor unit conversion on BMW sensors #110272
Allow per-sensor unit conversion on BMW sensors #110272
Conversation
Hey there @gerard33, mind taking a look at this pull request as it has been labeled with an integration ( Code owner commandsCode owners of
|
8c3c565
to
5c422a9
Compare
Is the below review requirement from HA staff or you @rikroe ? |
Not sure If I follow. This PR can only be merged by the HA team and unfortunately they haven't had time to review it (if thats what you asked). |
5c422a9
to
f797be2
Compare
Any idea when this will be implemented? |
) | ||
if isinstance(state, (ValueWithUnit, Enum)): | ||
state = state.value | ||
self._attr_native_value = cast(StateType, state) |
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 don't think you need to cast
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.
You're right, removed it.
@@ -85,6 +88,7 @@ | |||
StateSnapshot({ | |||
'attributes': ReadOnlyDict({ | |||
'attribution': 'Data provided by MyBMW', | |||
'device_class': 'distance', |
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 would expect it would look like this
'device_class': 'distance', | |
'device_class': '<Sensor device class=distance,>', |
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 seems to be coming up only when iterating over config entries as done e.g. in the airly
tests.
I don't think it makes a difference.
@@ -34,17 +34,17 @@ async def test_entity_state_attrs( | |||
("entity_id", "unit_system", "value", "unit_of_measurement"), | |||
[ | |||
("sensor.i3_rex_remaining_range_total", METRIC, "279", "km"), | |||
("sensor.i3_rex_remaining_range_total", IMPERIAL, "173.36", "mi"), | |||
("sensor.i3_rex_remaining_range_total", IMPERIAL, "173", "mi"), |
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 remove the rest? Might as well include it now and use suggested_display_precision in the entity descriptions
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.
Set the display precision, but now had to add the full length converted value, as HA will print the full float as string state value.
Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍 |
fb0c603
to
d6b137f
Compare
@@ -83,83 +73,96 @@ def convert_and_round( | |||
key="charging_status", | |||
translation_key="charging_status", | |||
key_class="fuel_and_battery", | |||
value=lambda x, y: x.value, | |||
device_class=SensorDeviceClass.ENUM, | |||
options=[s.value.lower() for s in ChargingState if s != ChargingState.UNKNOWN], |
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.
@MartinHjelmare Usually we discourage developers to do this because "what if the library changes?", but in this case the options are fixated in the snapshots, so whenever the enum changes and the library is bumped (without regenerating the snapshots) tests would fail. So the only thing left is that the reviewer should know that a string should be added to the strings.
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 still don't think it's a good idea to take that approach. The same reasoning still applies. The integration should blow up if an option is missing in the translations.
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.
But that can also happen if someone just adds a value to "a random list in const.py" without adding the transition key? It both comes down to the alertness of the reviewer on this. (And imo, with these snapshots it's even more clear what this change is and that a key should be added)
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.
The integration should blow up if an option is missing in the translations.
I implemented a separate test only for the translations to make it clear after a library update if translations are missing (see latest commit).
Then users would not get error messages it is already part of the testing pipeline.
If a translation key is missing (or malformed), pytest assertion would throw an error similar to this:
> assert all_sensor_options == all_translation_options
E AssertionError: assert {'component.b...ot_full', ...} == {'component.b...ot_full', ...}
E
E Extra items in the left set:
E 'component.bmw_connected_drive.entity.sensor.charging_status.state.error'
E Extra items in the right set:
E 'component.bmw_connected_drive.entity.sensor.charging_status.state.error1'
E Use -v to get more diff
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.
Oh you added a full test for it, my point was more saying that having a way to fixate the options list somewhere would suffice instead of duplicating all enums.
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.
Wondering what I can do for this to go through?
Just pinning the enum sensors?
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 have reverted (i.e. pinned) the Enum values so this PR can be (hopefully) merged.
I might create another draft PR with a corresponding architecture discussion as I think that Enum values from a library should be allowed, provided there are tests if all translations are available.
ChargingState.DEFAULT, | ||
ChargingState.CHARGING, | ||
ChargingState.ERROR, | ||
ChargingState.COMPLETE, | ||
ChargingState.FULLY_CHARGED, | ||
ChargingState.FINISHED_FULLY_CHARGED, | ||
ChargingState.FINISHED_NOT_FULL, | ||
ChargingState.INVALID, | ||
ChargingState.NOT_CHARGING, | ||
ChargingState.PLUGGED_IN, | ||
ChargingState.WAITING_FOR_CHARGING, | ||
ChargingState.TARGET_REACHED, |
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.
Which one is missing?
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.
Not sure if I follow. The only Enum not in this list is ChargingState.UNKNOWN
as this is not a valid state and (from previous comments) should be 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.
But now we fixate the options in the snapshot, so we can do [x.lower() for x in ChargingState where ChargingState is not CharginState.UNKNOWN]
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'm sorry, I thought the discussion about this with @MartinHjelmare (#110272 (comment)) was the reason this PR was stuck.
Thats why I reverted this in 947c8b8.
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.
Yes that was the original point of the PR, but I still believe this is a non-issue because we got it covered. I spoke Frenck today and he was like "why not"
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.
Many thanks! Added the list comprehensions back in.
ClimateActivityState.COOLING, | ||
ClimateActivityState.HEATING, | ||
ClimateActivityState.INACTIVE, | ||
ClimateActivityState.STANDBY, |
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.
idem
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.
Same as ChargingState
.
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.
Reverted
"finished_not_full": "Finished, not full", | ||
"invalid": "Invalid", | ||
"not_charging": "Not charging", | ||
"plugged_in": "Plugged Ii", |
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.
typo?
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, fixed
"fully_charged": "Fully charged", | ||
"finished_fully_charged": "Fully charged", |
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.
Having 2 the same states doesn't make a lot of sense imo
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.
Yeah - the issue is we don't really know which of these enums could occur, they are collected over multiple years.
Therefore I decided in this case to combine both, but I can also have different translations if you feel this is needed.
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.
The thing I am worried about is that with this change when you edit an automation and select a possible state, you see "Fully charged" twice and never know which one is triggered when. So imagine created an automation for Fully charged 1, and then the car actually displays 2, that's strange.
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.
+1, I agree on this.
I'll translate it for now and then have to think later how to deal with this ever growing list.
As discussed with @joostlek, I have remove (almost) all changes regarding sensor enums for two reasons:
While I know that the code does not fully adhere to standards, it is not worse than before. I'll create a seperate PR to address the sensor enum issues separately. |
* Update BMW sensors to use device_class * Test adjustments * Trigger CI * Remove unneeded cast * Set suggested_display_precision to 0 * Rebase for climate_status * Change charging_status to ENUM device class * Add test for Enum translations * Pin Enum sensor values * Use snapshot_platform helper * Remove translation tests * Formatting * Remove comment * Use const.STATE_UNKOWN * Fix typo * Update strings * Loop through Enum sensors * Revert enum sensor changes --------- Co-authored-by: Richard <rikroe@users.noreply.github.com>
* Update BMW sensors to use device_class * Test adjustments * Trigger CI * Remove unneeded cast * Set suggested_display_precision to 0 * Rebase for climate_status * Change charging_status to ENUM device class * Add test for Enum translations * Pin Enum sensor values * Use snapshot_platform helper * Remove translation tests * Formatting * Remove comment * Use const.STATE_UNKOWN * Fix typo * Update strings * Loop through Enum sensors * Revert enum sensor changes --------- Co-authored-by: Richard <rikroe@users.noreply.github.com>
Proposed change
This PR updates the BMW sensors to use the default unit conversion in HomeAssistant via
device_class
andnative_unit_of_measure
.The precision of the conversion to imperial units has been removed from the tests, but works on a per-entity basis if #110270 is merged.
Type of change
Additional information
Checklist
ruff format 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
.To help with the load of incoming pull requests: