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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial support fo HomematicIP components #12761

Merged
merged 9 commits into from
Mar 18, 2018
Merged

Add initial support fo HomematicIP components #12761

merged 9 commits into from
Mar 18, 2018

Conversation

worm-ee
Copy link
Contributor

@worm-ee worm-ee commented Feb 27, 2018

Description:

Initial support fo HomematicIP components

Example entry for configuration.yaml (if applicable):

homematicip:
  - name: 'Somewhere'
    accesspoint: !secret homematicip_accesspoint
    authtoken: !secret homematicip_authtoken

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 have been added to the REQUIREMENTS variable (example).
  • New dependencies are only imported inside functions that use them (example).
  • New dependencies have been added to requirements_all.txt by running script/gen_requirements_all.py.
  • New files were added to .coveragerc.

@homeassistant
Copy link
Contributor

Hello @mxworm,

When attempting to inspect the commits of your pull request for CLA signature status among all authors we encountered commit(s) which were not linked to a GitHub account, thus not allowing us to determine their status(es).

The commits that are missing a linked GitHub account are the following:

Unfortunately, we are unable to accept this pull request until this situation is corrected.

Here are your options:

  1. If you had an email address set for the commit that simply wasn't linked to your GitHub account you can link that email now and it will retroactively apply to your commits. The simplest way to do this is to click the link to one of the above commits and look for a blue question mark in a blue circle in the top left. Hovering over that bubble will show you what email address you used. Clicking on that button will take you to your email address settings on GitHub. Just add the email address on that page and you're all set. GitHub has more information about this option in their help center.

  2. If you didn't use an email address at all, it was an invalid email, or it's one you can't link to your GitHub, you will need to change the authorship information of the commit and your global Git settings so this doesn't happen again going forward. GitHub provides some great instructions on how to change your authorship information in their help center.

    • If you only made a single commit you should be able to run
      git commit --amend --author="Author Name <email@address.com>"
      
      (substituting Author Name and email@address.com for your actual information) to set the authorship information.
    • If you made more than one commit and the commit with the missing authorship information is not the most recent one you have two options:
      1. You can re-create all commits missing authorship information. This is going to be the easiest solution for developers that aren't extremely confident in their Git and command line skills.
      2. You can use this script that GitHub provides to rewrite history. Please note: this should be used only if you are very confident in your abilities and understand its impacts.
    • Whichever method you choose, I will come by to re-check the pull request once you push the fixes to this branch.

We apologize for this inconvenience, especially since it usually bites new contributors to Home Assistant. We hope you understand the need for us to protect ourselves and the great community we all have built legally. The best thing to come out of this is that you only need to fix this once and it benefits the entire Home Assistant and GitHub community.

Thanks, I look forward to checking this PR again soon! ❤️

@pvizeli
Copy link
Member

pvizeli commented Feb 28, 2018

cc @danielperna84, maybe @balloob

I think the name suggestion is wrong. Maybe homematicip_rest or homematicip_accesspoint. The homematic component access directly to driver they use xmlrpc. The AccessPoint use the same driver but don't allow to access directly to his driver. Maybe iq3 allow in future to access directly to his internal xmlrpc like (o)ccu2 and you can also use homematic component and user they use (O)CCU2 have also access to homematicip device and don't can use this for access. Anyway, mabye we need rename homematic to homematic_xmlrpc?

My personal: this interface is not public from EQ3. Buy a raspberrypi3 and HomeMaticIP USB stick from ELV and use the hass.io add-on or other implementation for this and you need never care about any firmware updates they change things on interface. CCU2 from EQ3 work also.

@worm-ee
Copy link
Contributor Author

worm-ee commented Feb 28, 2018

Hi, I have added my email address to GitHub.

Ciao Mattias

@danielperna84
Copy link
Contributor

Anyway, mabye we need rename homematic to homematic_xmlrpc?

I would vote against that. homematic is intuitive and will be what most people will use anyways. To me it seems ok to call this new component homematicip.

Also I do see a value in this component. People who once started out with the IP access point and now want to have a look how it works with HA should be able to do that. A reverse engineered approach though may break as soon as eq3 breaks it with some firmware update.
So as long as eq3 doesn't open up the API I see this as an experimental custom component. We could link to that from the Homematic documentation for people who are in search for a solution if the just have the IP access point.

last = self._device.lastStatusUpdate
if last is not None:
attr.update({ATTR_LASTSTATUS_UPDATE:
last.strftime('%d-%m-%Y %H:%M:%S')})
Copy link
Member

Choose a reason for hiding this comment

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

last.isoformat()

@balloob balloob removed the cla-error label Feb 28, 2018
@balloob
Copy link
Member

balloob commented Feb 28, 2018

Shouldn't this be integrated into pyhomematic? It's just another channel that gives the same information right?

@danielperna84
Copy link
Contributor

Shouldn't this be integrated into pyhomematic? It's just another channel that gives the same information right?

No, this targets a different hub-device that's not accessable via the same API. pyhomematic (for usage with the classic Homematic hub) uses XML-RPC to set states and has a XML-RPC server thread to receive the state changes (local push in HA-terms).
The IP access point (the new hub with cloud integration, but without official local API) this component is about uses (as far as I know) REST to set states and allows to receive state changes via a websocket connection. So the relation between these two would be more comparable to the Hue bridge and the Tradfri bridge. Doing similar stuff, but the implementation is rather different.

@worm-ee
Copy link
Contributor Author

worm-ee commented Feb 28, 2018

Hi, yes I agree... all data is going to the HMIP cloud servers and then back to the access point. But a least there is a bit of direct communication between the different devices.
But "homematicip_rest" might be the proper name.

By the way: how do I have to import the homematicip module?

  1. implemented at the moment but not passing tox
    -- snip --
    from homeassistant.helpers.discovery import load_platform
    from homematicip.home import Home
    REQUIREMENTS = ['homematicip==0.8']
    _LOGGER = logging.getLogger(name)
    -- snap --
  2. passing tox but not pylint
    -- snip --
    def setup(hass, config):
    """Set up the HomematicIP component."""
    from homematicip.home import Home
    hass.data.setdefault(DOMAIN, {})
    -- snap --

Thanks Mattias

@balloob
Copy link
Member

balloob commented Feb 28, 2018

@danielperna84 thanks for the explanation.

2 is the correct one. You just didn't run script/gen_requirements_all.py (see PR description)

I don't think that we should name the component after the interface that is being used to communicate. It should be named after the API name. One should be able to speak this API over the cloud or locally, it shouldn't matter what the name is. Even REST is an implementation detail (and a bad name as it uses websockets too?)

Do the new generation of homematic hubs have a name? or maybe the API?

@worm-ee
Copy link
Contributor Author

worm-ee commented Mar 1, 2018

Hi,

Can someone help me to understand what went wrong in the travis build?

Thanks Mattias

@balloob
Copy link
Member

balloob commented Mar 1, 2018

@mxworm just a flaky test, I restarted your build.

@pvizeli
Copy link
Member

pvizeli commented Mar 1, 2018

What is with homematic_cloud? So homematic call the local driver with xmlrpc and the homematic_cloud use the EQ3 cloud service. Maybe with more device as hmIP in future. homematic support also wired, rf and ip devices.

@worm-ee
Copy link
Contributor Author

worm-ee commented Mar 1, 2018

@pvizeli I would like to keep complexity low - there are already a lot of HMIP components :-)
If you want to rename the component I would go for homematicip_cloud.

@balloob
Copy link
Member

balloob commented Mar 1, 2018

Oh, heh. My bad, I didn't realize that Homematic IP is the product name. I'm fine with naming it just homematic_ip.py then. Sorry for the confusion. I thought you added IP because it communicated over IP.

@worm-ee
Copy link
Contributor Author

worm-ee commented Mar 2, 2018

@balloob I would keep the naming for the moment, whats next?

async_dispatcher_connect(
self.hass, EVENT_DEVICE_CHANGED, self._device_changed)

@callback
Copy link
Member

Choose a reason for hiding this comment

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

FYI, this one is correctly async. The dispatcher will execute this method in an async context because of this decorator.


def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the HomematicIP sensors devices."""
# pylint: disable=import-error, no-name-in-module
Copy link
Member

Choose a reason for hiding this comment

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

These shouldn't have to be disabled since you updated requirements_all.txt

"""Initialize the access point sensor."""
self.hass = hass
self._home = home
async_dispatcher_connect(
Copy link
Member

Choose a reason for hiding this comment

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

Use sync version

@pvizeli
Copy link
Member

pvizeli commented Mar 15, 2018

I like homematicip_cloud. It represent what it is 👍

@worm-ee
Copy link
Contributor Author

worm-ee commented Mar 15, 2018

Hi folks, I would love to add some more components e.g binary_switches, climate and security for HomematicIP. But first I would like to clarify the name of the platform. homematicip_cloud is fine for me, if everyone involved agrees I will change the name.

@balloob
Copy link
Member

balloob commented Mar 16, 2018

Please do not add more types in this PR. Let's get this PR merged and then add more types in a follow up PR.

I am fine with homematicip_cloud 👍

@worm-ee
Copy link
Contributor Author

worm-ee commented Mar 16, 2018

Yes, I agree this PR is already a bit of a mess... sorry for that. Its my first PR on such a big project and my python is quite limited. Thanks for the support. I will rename as a last thing in this PR, next devices will be provided as separate PRs.

@balloob
Copy link
Member

balloob commented Mar 18, 2018

Awesome work! 🎉 Good to go!

When adding platforms to this component, please stick to 1 platform / PR. That will make reviewing and merging a lot faster.

@balloob balloob merged commit b45dad5 into home-assistant:dev Mar 18, 2018
Copy link
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.

Left comments for a future PR.

Support for HomematicIP components.

For more details about this component, please refer to the documentation at
https://home-assistant.io/components/homematicip/
Copy link
Member

Choose a reason for hiding this comment

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

Please update the url to point at the new component name.

from socket import timeout

import voluptuous as vol
from homeassistant.core import callback
Copy link
Member

Choose a reason for hiding this comment

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

Please add a blank line between 3rd party and homeassistant imports.


DOMAIN = 'homematicip_cloud'

CONF_NAME = 'name'
Copy link
Member

Choose a reason for hiding this comment

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

Import this from const.py.

authtoken = device.get(CONF_AUTHTOKEN)

home = Home()
if name.lower() == 'none':
Copy link
Member

Choose a reason for hiding this comment

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

When will this happen? Default name is an empty string in the config schema.

Support for HomematicIP sensors.

For more details about this component, please refer to the documentation at
https://home-assistant.io/components/homematicip/
Copy link
Member

Choose a reason for hiding this comment

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

Look at other platforms for the format of the url.

"""Initialize the access point sensor."""
self.hass = hass
self._home = home
dispatcher_connect(
Copy link
Member

Choose a reason for hiding this comment

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

Move this to the coroutine method async_added_to_hass, to avoid a race where the callback is called before the entity has been added to home assistant.

class HomematicipAccesspoint(Entity):
"""Representation of an HomeMaticIP access point."""

def __init__(self, hass, home):
Copy link
Member

Choose a reason for hiding this comment

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

Don't pass in hass. It will be set on the entity when it has been added to home assistant.

class HomematicipGenericDevice(Entity):
"""Representation of an HomematicIP generic device."""

def __init__(self, hass, home, device, signal=None):
Copy link
Member

Choose a reason for hiding this comment

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

Don't pass in hass. It will be set on the entity when it has been added to home assistant.

Copy link
Member

Choose a reason for hiding this comment

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

signal parameter doesn't seem to be used.

self.hass = hass
self._home = home
self._device = device
async_dispatcher_connect(
Copy link
Member

Choose a reason for hiding this comment

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

Move this to the coroutine method async_added_to_hass.

@sander76
Copy link
Contributor

@mxworm @balloob @MartinHjelmare The homematic-rest-api also has a asyncio component. I created a custom hmip component using the asyncio capabilities with the intention of later creating a component out of it.

I paid a lot of attention making the websocket implementation robust as I experienced frequent connection drops making hass losing track of state changes rendering the component useless. This involved changing the websocket code on the library as well as on my custom component side. This has all been done on the asyncio part of the homematic-rest-api library.

Do you have any experience with the code which is just merged and the robustness of the websocket connection ?

I really think this needs some more attention...

For reference: Here is my custom component:
https://github.com/sander76/custom_components

@balloob
Copy link
Member

balloob commented Mar 21, 2018

FYI if you want a (in my opinion) good example of an asyncio aiohttp websocket connection with retry logic, check the Home Assistant Cloud code: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/cloud/iot.py

@sander76
Copy link
Contributor

@ballob Thanks.
My retry logic was inspired by https://github.com/armills/aioautomatic

I faced issues with the heartbeat parameter in aiohttp. Hopefully with the new release that has changed.

My custom component is now running without any issues for 2 months now. It took a while to get there as the homematic webserver is/used to be notoriously unstable. (They are making great progress and as a whole the platform absolutely rocks).

Question remains what to do with this pull request?

Obviously I highly appreciate the effort made by @mxworm, but I am also sure this component will stop working after a while. That is bad for hass.

I am also reluctant to improve on this PR as I have my own implementation. Which is really different from this one.

@worm-ee
Copy link
Contributor Author

worm-ee commented Mar 22, 2018

@sander76
I have also a reconnect code, but not yet committed, but anyhow you implementation is async which might be better for home assistent.
I can also understand that you don't want to modify the PR. What about to team-up an I merge your code to this initial support? There is not much difference between you and my component code - you are also using a sort of general sensor class(Entity). I would keep you naming of the classes and proprieties.

Would this be way to go for?

@balloob
If Sander agrees I would start to merge after the merge of my cleanup PR.

Ciao

@sander76
Copy link
Contributor

@mxworm
You're more than welcome !
I am going to have a look balloob's suggestion on his websocket reconnection code...

@sander76
Copy link
Contributor

@mxworm Please let me know which repo you'll be using for making the changes. I will try to help where possible. Looking at the code from balloob my code can use a bit of improving too...

@worm-ee
Copy link
Contributor Author

worm-ee commented Mar 22, 2018

@sander76 OK, then I will use for the moment your last code from https://github.com/sander76/custom_components
I will be on vacation next week, lets see how far I get in the next days. Small updates on your web socket code we can do later as well.

I would like to implement climatic devices and groups as well. But first I would like to have a solid base for further development.

@balloob Would this be OK for you as well? I know its annoying to have a complete rewrite of the code after the first PR.

@sander76
Copy link
Contributor

@mxworm @balloob Would it be possible to reject this merge and start over ?

@worm-ee
Copy link
Contributor Author

worm-ee commented Mar 22, 2018

@balloob @sander76 I think its not necessary, there is only the platform and the sensor component so far. I will move my code to async to have a proper baseline and file the PR in the next days.

@sander76
Copy link
Contributor

@mxworm
Check out here:
https://github.com/sander76/custom_components/tree/changing_reconnect

First shot at balloobs suggestion. Much cleaner.
Thanks @balloob !

@balloob
Copy link
Member

balloob commented Mar 22, 2018

Let's not pull out this PR. It's fine for the PR to be released and the guts changed out in the next PR. Would be a non breaking change for users since the config options should not change.

@balloob balloob mentioned this pull request Mar 30, 2018
@sander76
Copy link
Contributor

sander76 commented Apr 14, 2018

@mxworm Did you already make a start with moving to async ? Please let me know, I can help. If not, is it ok if I give it a go ?

@worm-ee
Copy link
Contributor Author

worm-ee commented Apr 14, 2018

@sander76 So far there is a PR pending with a async version, but just with sensors.
#13468

All components I have implemented you can find under:
https://github.com/mxworm/home-assistant/tree/add-homematicip_cloud-alarm_panel-component
I just waiting for the merge then I will add features splitter over several PR as requested from the team.

@home-assistant home-assistant locked and limited conversation to collaborators Apr 15, 2018
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.

None yet

7 participants