-
-
Notifications
You must be signed in to change notification settings - Fork 28.6k
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
Add new component: BMW connected drive #12277
Conversation
from bimmer_connected import BimmerConnected | ||
self.bimmer = BimmerConnected(vin, username, password, cache=True) | ||
self.name = name | ||
|
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.
blank line at end of file
@ChristianKuehnel, let's get in touch to see how we can join forces. I my version the VIN isn't needed and I have some extra sensors and also switches in use. I was facing an issue however with warnings that updating the sensors took longer than the scheduled update interval of 0:00:30. @danielperna84 was just now helping me to find the cause of that issue. |
What I noticed while looking at bimmer-connected: it uses the german API endpoint. Having followed the thread @gerard33 has mentioned it is actually required to be able to use different URLs so people from other countries can use this as well. |
I tried to use the German url and that actually worked, but then I got errors using the BMW CD app, so using the local url is indeed the best solution. |
@gerard33 just commented on the community page, lets discuss there how to proceed. |
* Update are now triggered from BMWConnectedDriveVehicle. * removed polling from sensor and device_tracker * backend URL is not detected automatically based on current country * vehicles are discovered automatically * updates are async now resolves: * bimmerconnected/bimmer_connected#3 * bimmerconnected/bimmer_connected#5
""" | ||
import logging | ||
|
||
from homeassistant.components.bmw_connected_drive \ |
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.
'homeassistant.components.bmw_connected_drive.BMWConnectedDriveEntity' imported but unused
password = account_config[CONF_PASSWORD] | ||
country = account_config[CONF_COUNTRY] | ||
_LOGGER.debug('Adding new account %s', name) | ||
bimmer = BMWConnectedDriveEntity(hass, username, password, country, name) |
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.
line too long (81 > 79 characters)
@danielperna84 the portal is now selected based on the country you define as config parameter. @gerard33 I'm done with my major refactoring of the setup and update process. Now the update is triggered by a timer in the |
I ran the current implementation over the last 24 hours in my test setup and it worked fine. It does not yet contain all the values you could get from your BMW but I think we could start rolling it out and get some feedback from the users. I suspect there might be some issues with different BMW models and different countries. There is a ton of more features available from the BMW portal, but we can add these later on. |
@MartinHjelmare thx for the extensive code review! I just uploaded the changes. To be honest, I did not really understand how async works in Home Assistant. Is there a good documentation available? |
Did you see https://home-assistant.io/developers/asyncio/? |
'mileage', | ||
] | ||
|
||
VAILD_ATTRIBUTES = LENGTH_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.
Typo, same as before.
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.
Ah, yes was a copy an past error. I removed the duplicated code.
def add_update_listener(self, listener): | ||
"""Add a listener for update notifications.""" | ||
self._update_listeners.append(listener) | ||
listener() |
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 should call the callback from this method. It's better to separate responsibilities, and let the caller call the callback explicitly if 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.
OK
) | ||
|
||
@asyncio.coroutine | ||
def async_added_to_hass(self): |
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 can't use this method here, since this is not an entity. The device tracker component is special like that. It creates its own entities and you can only create a device class that reports to the entity via the see
method.
I don't think there will be a race for the device tracker if you register and call the callback during setup_scanner
.
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.
OK
Show latest data after startup. | ||
""" | ||
self._account.add_update_listener(self.update) | ||
self.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.
Remove this.
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.
What should I remove?
The self.update()
? I need this so the state of the sensor is available right after the start of hass. If I want to trigger this from the central component, I would have to find out when all of the setup operations were completed.
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 remove this line here. See my comment above about how to add devices so that update will be called when they are 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.
Ok, so an alternative if you really want to keep the logging with entity_id in update
is to schedule a call to update
here. In that case, use yield from self.hass.async_add_job(self.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.
When I call add_devices(devices, True)
from setup_platform
even without me logging the entity_id, I get this error:
2018-02-19 16:55:32 ERROR (MainThread) [homeassistant.core] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
result = coro.send(None)
File "/home/kuehnelc/git/home-assistant/homeassistant/helpers/entity.py", line 196, in async_update_ha_state
"No entity id specified for entity {}".format(self.name))
homeassistant.exceptions.NoEntitySpecifiedError: No entity id specified for entity 530i xDrive remaining_range_fuel
I'm not sure why that is.
Your version with yield from self.hass.async_add_job(self.update)
works just as fine as self.update()
. So I'll take your version. Not sure why you want update do be called via async_add_job
, it's only doing a bit of string processing. There is no IO in the update function. But as it works, I'm fine with that 😄 ...
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 update
method calls schedule_update_ha_state
which needs to be done from a sync context.
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.
Regarding error, yeah sorry, the entity_id
is also required when scheduling a state update, ie in schedule_update_ha_state
, so the my suggestion to call add_devices
like that was totally wrong. The logic about this changed recently and I hadn't really understood all the consequences until now.
for sensor in VALID_ATTRIBUTES: | ||
device = BMWConnectedDriveSensor(account, vehicle, sensor) | ||
devices.append(device) | ||
return add_devices(devices) |
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.
Remove the return. Just call add_devices(devices, True)
to have the update
method be called during entity addition.
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.
add_devices(devices, True)
resulted in some weird "no entity_id set" errors.
But `add_devices(devices)' (without true) works just fine.
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.
Ok, the entity_id will not be set during the update before add operation. All other attributes will be available though. Either remove the logging about entity_id in update
, or do the schedule the update from async_added_to_hass
.
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 looks good! Fix the final comment and we can merge.
"""Initialize the Tracker.""" | ||
self._see = see | ||
self.vehicle = vehicle | ||
self._account = account |
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 doesn't seem to be used.
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.
Ah yes, you have a good eye for these things...
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.
Great!
@MartinHjelmare thx for your help! 👍 😄 @gerard33 good news, it's merged 🥂 So you can now add your additional sensors on top of the dev branch. |
@ChristianKuehnel @gerard33 I have a i3 and I am interested in helping although I don't have too much experience in Python, I am pretty good at other languages. How can I help make this better? |
@robbz23 |
Sorry I'm an American living in Sweden. Both the component and extra work. |
1 similar comment
Sorry I'm an American living in Sweden. Both the component and extra work. |
Description:
This is a basic implementation of a sensor for BMW Connected Drive vehicles. In the current version your're getting:
I could only test this with one BMW model. So there might be changes necessary to make it work with other models...
Related issue (if applicable): N/A
Pull request in home-assistant.github.io with documentation (if applicable): home-assistant/home-assistant.io#4617
Example entry for
configuration.yaml
(if applicable):Checklist:
If user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
tox
run successfully. Your PR cannot be merged unless tests passREQUIREMENTS
variable (example).requirements_all.txt
by runningscript/gen_requirements_all.py
..coveragerc
.