Add sensors for BMW electric cars#14293
Add sensors for BMW electric cars#14293MartinHjelmare merged 4 commits intohome-assistant:devfrom gerard33:bmw-electric
Conversation
|
Just tested this and it is not recognizing my car as electrical (it is an i3) |
|
@rafale77 can you share a screenshot with all the cars entities from the States page? |
|
I was looking for it and actually there is none of the additional sensors. Not sure if I pulled this wrong. I am in US. Not sure if the server has an impact. |
|
Server should not have impact, so probably something with the pull. |
|
Sorry for the wrong message, I oddly had two version of Hass installed and updating no longer updates my virtual env one which is strange. It is all working. |
| # device class plug: On means device is plugged in, | ||
| # Off means device is unplugged | ||
| if self._attribute == 'connection_status': | ||
| self._state = bool(vehicle_state._attributes['connectionStatus'] == |
There was a problem hiding this comment.
You don't need to use bool here.
| elif self._attribute == 'charging_level_hv': | ||
| return '%' | ||
| else: | ||
| self._unit_of_measurement = None |
There was a problem hiding this comment.
Changed it to return None
| @@ -53,8 +45,6 @@ def __init__(self, account, vehicle, attribute: str, sensor_name, icon): | |||
| self._unit_of_measurement = None | |||
| result[window.name] = window.state.value | ||
| elif self._attribute == 'door_lock_state': | ||
| result['door_lock_state'] = vehicle_state.door_lock_state.value | ||
| result['last_update_reason'] = vehicle_state.last_update_reason |
There was a problem hiding this comment.
This function is not getting a huge if/elseif statement. This makes it a bit hard to read and maintain. Should we split up this monster class into one class per sensor type and use inheritance?
There was a problem hiding this comment.
That sounds like a plan. I would suggest to discuss this seperately, so we can first get this PR finished. Then we can implement the other parts on our list, such as sending the position, the imperial vs metric units, the lscType and the stuff you mentioned here regarding the design and readability of the code.
| device = BMWConnectedDriveSensor(account, vehicle, key, | ||
| value[0], value[1]) | ||
| devices.append(device) | ||
| if vehicle.has_hv_battery: |
There was a problem hiding this comment.
You could also use vehicle.drive_train_attributes here. This will already give you a list of available attributes. This way you're flexible if we add more attributes to bimmer_connected.
Then you would not need SENSOR_TYPES_ELEC and SENSOR_TYPES
There was a problem hiding this comment.
The vehicle.drive_train_attributes is being used in the sensor code.
It contains a lot of attributes, but not the ones which are used for the binary_sensors (only charging_status is used in both).
Maybe it's a good idea to add this to bimmer_connected for the binary sensors as well in a next release.
| elif self._attribute == 'lights_parking': | ||
| result['lights_parking'] = vehicle_state.parking_lights.value | ||
| elif self._attribute == 'condition_based_services': | ||
| for report in vehicle_state.condition_based_services: |
There was a problem hiding this comment.
You could extract the formatting of the CBS data into a separate function:
@staticmethod
def _format_cbs_report(report):
result = dict()
service_type = report.service_type.lower().replace('_', ' ')
...
return resultThis would make the function more readable.
There was a problem hiding this comment.
Or maybe also something that can be done in bimmer_connected?
Otherwise I can indeed make a separate function for this in a next version.
There was a problem hiding this comment.
@gerard33
I just had a look at the code and this is quite specific for the HA use case, where you need a dictionary as result. I would rather not implement this in bimmer connected.
| # Possible values: LOCKED, SECURED, SELECTIVE_LOCKED, UNLOCKED | ||
| self._state = vehicle_state.door_lock_state not in \ | ||
| [LockState.LOCKED, LockState.SECURED] | ||
| # device class light: On means light detected, Off means no light |
There was a problem hiding this comment.
Similar: huge if statement for the different types of sensors.
There was a problem hiding this comment.
See my first comment.
| elif self._attribute == 'charging_status': | ||
| result['charging_status'] = vehicle_state.charging_status.value | ||
| result['last_charging_end_result'] = \ | ||
| vehicle_state._attributes['lastChargingEndResult'] |
There was a problem hiding this comment.
Travis is failing on three of these accesses to private attributes. You can disable that check above those lines. But you should probably change this in the library so that we don't have to access private attributes.
There was a problem hiding this comment.
Thanks! Have disabled those checks for now. It's on the issue list to add these to the library
bimmerconnected/bimmer_connected#73.
| charging_state = vehicle_state.charging_status in \ | ||
| [ChargingState.CHARGING] | ||
|
|
||
| if self._attribute == 'mileage': |
There was a problem hiding this comment.
You could make a constant dict that maps the attributes to the icon and lookup that here, if attribute is not charging_level_hv.
| def unit_of_measurement(self) -> str: | ||
| """Get the unit of measurement.""" | ||
| return self._unit_of_measurement | ||
| if self._attribute in ( |
There was a problem hiding this comment.
You could use a dict here too.
|
I'm going to merge this now. A new PR that cleans up some of the if...elif trails would be great. |
Description:
Add new sensors for BMW vehicles.
CC @ChristianKuehnel @m1n3rva
General:
parking_lightscondition_based_servicescheck_control_messagesFor electric and hybrid cars:
charging_statusconnection_statuscharging_time_remainingcharging_statusmax_range_electriccharging_level_hvremaining_range_electricBreaking change
The current sensor
remaining_range_fuelis replaced byremaining_range_totalfor cars with a combustion engine.Checklist:
tox. Your PR cannot be merged unless tests pass