Skip to content

Add extra sensors for BMW ConnectedDrive#12591

Merged
MartinHjelmare merged 10 commits intohome-assistant:devfrom
gerard33:bmw-connecteddrive
Mar 15, 2018
Merged

Add extra sensors for BMW ConnectedDrive#12591
MartinHjelmare merged 10 commits intohome-assistant:devfrom
gerard33:bmw-connecteddrive

Conversation

@gerard33
Copy link
Copy Markdown
Contributor

@gerard33 gerard33 commented Feb 21, 2018

Description:

The following items are added to BMW ConnectedDrive:

  • Binary sensors for Doors, Windows and Door lock state
  • Lock

For the existing sensors remaining_range_fuel, mileage and remaining_fuel the attribute car: <car_model> and an applicable mdi icon are added.

Breaking change reverted in #13380


Pull request in home-assistant.github.io with documentation (if applicable): home-assistant/home-assistant.io#4733

Checklist:

  • The code change is tested and works locally.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • Local tests with tox run successfully. Your PR cannot be merged unless tests pass
  • New dependencies are only imported inside functions that use them (example).

@gerard33
Copy link
Copy Markdown
Contributor Author

@ChristianKuehnel I have added the binary sensor, lock and made some small changes to the existing sensor. Can you please review these?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Binary sensors don't have a unit of measurement.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please sort 🔤 within groups standard library, 3rd party and homeassistant.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Time stamp is not allowed in state attributes. The state should not update just because of a time change.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This shows the last update time which is received from the car via the bmw_connected_drive module.
This time stamp is only updated together with other updates received from the car, e.g. an update on the mileage, see the screenshot below.

It's the same usage as in the Mercedes ME component.

screenshot_7

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@gerard33
I get your point, I agree it's quite useful to see when the last measurement was taken. But isn't the information redundant? You would also get the age of the information from the headline "3 hours ago".

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, this is redundant, please remove it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

As a matter of fact it is not redudant. The last update contains the time on which the update from the car is received, but that doesn't always mean that every sensor is being updated. So this can result in a different time shown at the time information in the headline than at the last update time. See the example with the below screenshots.
With this update the door lock state has changed, but the windows state hasn't, resulting in different times for the windows sensor in the headline versus the last update time.

I think it has added value to show this attribute as you can easily see if the sensor has changed or not as part of the last update received from the car.

img_8122_2
img_8123_2

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If a state attribute changes, the last_updated attribute of the state will be updated with the time, so this information is already available in the the state machine. If a user wants to know about this we offer the template sensor which can display state attributes including last_updated. We shouldn't duplicate this information in the state machine.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is lid name lowercase snakecase? That's the home assistant standard.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It is, this is an example of a lid name: door_driver_front.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

👍

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is iterating windows not lids.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Changed it to window :)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Since we register a callback for state updates, I expect that the callback is called when the state has changed on the device, (car lock). Isn't that true? If that is true, the lock method should only call the device lock method.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Locking/unlocking the car doesn't trigger a state update.

Copy link
Copy Markdown
Contributor

@ChristianKuehnel ChristianKuehnel Feb 23, 2018

Choose a reason for hiding this comment

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

We're polling the update every 5 minutes. So if we do not change the state here, the UI will show an old state for 5 minutes.

And if we do poll right away, you still get the old state. You have to wait about 10 seconds until you get the correct state from the server.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think a middle way is to do an optimistic state update immediately in home assistant, then have the library call the update callback after 10 seconds with the correct state when we are sure that that is present.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

See above.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

See above.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Locking/unlocking the car doesn't trigger a state update.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Debug at most.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Changed to debug

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please remove.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

See my comment above an this last update time.

Copy link
Copy Markdown
Member

@MartinHjelmare MartinHjelmare left a comment

Choose a reason for hiding this comment

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

It would be best if the interface library made sure the update callback got called upon new state after the lock is locked/unlocked.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should probably be handled in the interface library.

Copy link
Copy Markdown
Contributor Author

@gerard33 gerard33 Feb 23, 2018

Choose a reason for hiding this comment

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

I have removed this check completly in here and will check with @ChristianKuehnel to handle this in the interface library and make that part of a next release.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sleeping is not allowed in the executor thread pool.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Either the update callback should handle setting state or we should do an optimistic state update from here, immediately. The logic below doesn't belong in this method.

Copy link
Copy Markdown
Contributor Author

@gerard33 gerard33 Feb 23, 2018

Choose a reason for hiding this comment

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

Removed, see above

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Don't use async methods from a sync context.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does the name of the sensor also contain the name of the vehicle?
If someone has more than one vehicle, we need to make sure that the sensors then get different names...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The vehicle name is not show in the sensor name, but it is shown in the attributes. Not sure what is the best approach, but maybe those people with more than one vehicle can update the friendly name of the sensor? Because in my opinion it's not necessary to show the vehicle name in the sensor name if you have one BMW (which will be the majority I guess).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we add an option where people can give names to their vehicles? Something like:

bmw_connected_drive:
  my_account:
    username: USERNAME_BMW_CONNECTED_DRIVE
    password: PASSWORD_BMW_CONNECTED_DRIVE
    country: COUNTRY_BMW_CONNECTED_DRIVE
    vehicles:
    - vin: SOMEVIN
      name: his
    - vin: SOMEOTHERVIN
      name: hers

That way people can

  • select which cars should be listed in HASS at all
  • set custom names for their vehicles
  • we have different names for the different vehicles?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That is indeed something we could add as an option.

Copy link
Copy Markdown
Member

@MartinHjelmare MartinHjelmare Feb 24, 2018

Choose a reason for hiding this comment

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

Please add a comment before this, saying why we need an optimistic state update, when we also have an update callback.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added the comments

@gerard33
Copy link
Copy Markdown
Contributor Author

Closing and opening the PR to trigger another Travis CI check.

@gerard33 gerard33 closed this Feb 25, 2018
@gerard33 gerard33 reopened this Feb 25, 2018
@MartinHjelmare
Copy link
Copy Markdown
Member

MartinHjelmare commented Feb 25, 2018

You changed access permissions for the requirements_all.txt file. Please revert that. That file should only be modified via the gen_requirements_all.py script.

Please also revert the access permission change on the component module.

@gerard33
Copy link
Copy Markdown
Contributor Author

Another close/open for Travis CI.

@gerard33 gerard33 closed this Feb 27, 2018
@gerard33 gerard33 reopened this Feb 27, 2018
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please update to version 0.4.1. I fixed some exceptions there and it's currently already in use on master

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

@ChristianKuehnel
Copy link
Copy Markdown
Contributor

@gerard33 Looks good to me.

As I updated to bimmer_connected version 0.4.1 on master you probably need to rebase your branch and re-run ./scripcs/gen-requirements.

Sorry for that, but I wanted to get the bugfix out quickly...

Copy link
Copy Markdown
Member

@MartinHjelmare MartinHjelmare left a comment

Choose a reason for hiding this comment

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

Please update the state update logic in all platforms. It will be more efficient and more on line with the rest of home assistant.

Also please remove the time stamp from all state attributes. It's redundant.

With that done this should be good to go.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, this is redundant, please remove it.

self._state = bool(vehicle_state.door_lock_state.value
in ('SELECTIVELOCKED', 'UNLOCKED'))

self.schedule_update_ha_state()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It would be more efficient if you move this to a separate new method which calls this with argument True which will make sure update is called before the state is updated.

Then register this new method as state update callback in async_added_to_hass.

def update_callback(self):
    """Schedule a state update."""
    self.schedule_update_ha_state(True)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated this, can you please doublecheck if it's okay?


Show latest data after startup.
"""
self._account.add_update_listener(self.update)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

self._account.add_update_listener(
    self.update_callback)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

Show latest data after startup.
"""
self._account.add_update_listener(self.update)
yield from self.hass.async_add_job(self.update)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Remove this and instead add an argument True to add_devices.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

device = BMWConnectedDriveSensor(account, vehicle, key,
value[0], value[1])
devices.append(device)
add_devices(devices)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

add_devices(devices, True)

This will make sure update is called before adding the device.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

for vehicle in account.account.vehicles:
device = BMWLock(account, vehicle, 'lock', 'BMW lock')
devices.append(device)
add_devices(devices)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

See above.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

self._state = (STATE_LOCKED if vehicle_state.door_lock_state.value
in ('LOCKED', 'SECURED') else STATE_UNLOCKED)

self.schedule_update_ha_state()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

See above.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done


Show latest data after startup.
"""
self._account.add_update_listener(self.update)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

See above.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

Show latest data after startup.
"""
self._account.add_update_listener(self.update)
yield from self.hass.async_add_job(self.update)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

See above.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done


def update(self) -> None:
"""Read new state data from the library."""
_LOGGER.debug('Updating %s', self.entity_id)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Replace this entity_id with name as in the other platforms.

Also please update the state update logic below as in the other platforms.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

Copy link
Copy Markdown
Member

@MartinHjelmare MartinHjelmare left a comment

Choose a reason for hiding this comment

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

Looks great!

@MartinHjelmare
Copy link
Copy Markdown
Member

Please add a paragraph and highlight the breaking changes in the description, so it's easy to copy paste that to the release notes.

@gerard33
Copy link
Copy Markdown
Contributor Author

@MartinHjelmare thanks!
I have added a paragraph in the description highlighting the breaking changes to the existing sensors.

@MartinHjelmare
Copy link
Copy Markdown
Member

Great!

@MartinHjelmare MartinHjelmare changed the title Added extra sensors for BMW ConnectedDrive Add extra sensors for BMW ConnectedDrive Mar 15, 2018
@MartinHjelmare MartinHjelmare merged commit d13bcf8 into home-assistant:dev Mar 15, 2018
@gerard33
Copy link
Copy Markdown
Contributor Author

@MartinHjelmare
cc @ChristianKuehnel

I just realized that the breaking change for the names of the sensors can be avoided.
I can leave the entity name of the sensor untouched and just add the new (more descriptive) name as friendly_name attribute to the sensors, so that name will be shown in the frontend together with the new mdi icons.

What do you think? If you agree I can make a PR (including the new binary sensors and lock) asap so this can be part of the HA 0.66 release.
Just let me know.

@MartinHjelmare
Copy link
Copy Markdown
Member

That won't work. We're not allowed to set friendly_name. What you can do is to set the entity_id. But I suggest you don't do that. Instead it would be better if we can define unique ids for each entity. Then the user can change entity_id if they want. Can we use the vin number?

@gerard33
Copy link
Copy Markdown
Contributor Author

Ah, I see.
Yes the VIN is available both in the current API as in the new API #13305.
I suggest adding the VIN to the entity_id in the new PR then?
And for now change the sensor name back to the currently used name to avoid having 2 breaking changes for this?

@MartinHjelmare
Copy link
Copy Markdown
Member

We should define unique_id property and use the vin number plus sensor type when applicable. Don't change entity_id.

@gerard33
Copy link
Copy Markdown
Contributor Author

Ok. And shall I adapt this PR so there is no breaking change in the name of the current 3 sensors?

Then the unique_id can be implemented in the WIP PR.

@MartinHjelmare
Copy link
Copy Markdown
Member

If the breaking name change can be avoided, that sounds good.

Try to only have one new feature per PR.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants