10000 Add support for MySensors cover by OttoWinter · Pull Request #3512 · home-assistant/core · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add support for MySensors cover #3512

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

Merged
merged 13 commits into from
Sep 30, 2016
Merged

Add support for MySensors cover #3512

merged 13 commits into from
Sep 30, 2016

Conversation

OttoWinter
Copy link
Member

Description:
Addition of support for MySensors cover.

Related issue (if applicable): Not applicable

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

Example entry for configuration.yaml (if applicable):
Not applicable.

Checklist:

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

If code communicates with devices, web services, or a:

  • Local tests with tox run successfully. Your PR cannot be merged unless tests pass
  • [N/A] New dependencies have been added to the REQUIREMENTS variable (example).
  • [N/A] New dependencies are only imported inside functions that use them (example).
  • [N/A] New dependencies have been added to requirements_all.txt by running script/gen_requirements_all.py.
  • [N/A] New files were added to .coveragerc.

If the code does not interact with devices:

  • [N/A] Local tests with tox run successfully. Your PR cannot be merged unless tests pass
  • [N/A] Tests have been added to verify that the new code works.

@@ -158,7 +158,7 @@ def gw_start(event):
'No devices could be setup as gateways, check your configuration')
return False

for component in 'sensor', 'switch', 'light', 'binary_sensor', 'climate':
for component in 'sensor', 'switch', 'light', 'binary_sensor', 'climate', 'cover':

Choose a reason for hiding this comment

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

farcy v1.1

  • 80: E501 line too long (86 > 79 characters)

@OttoWinter OttoWinter changed the title My sensors cover Added support for MySensors cover Sep 25, 2016
@OttoWinter OttoWinter changed the title Added support for MySensors cover Add support for MySensors cover Sep 25, 2016
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.

Three comments and also add set_cover_position back in. Mysensors do specify V_PERCENTAGE for cover and even if it didn't, we would want to use that, and we are free to do so.

Thanks for contributing!

pres = gateway.const.Presentation
set_req = gateway.const.SetReq
map_sv_types = {
pres.S_COVER: [set_req.V_UP],
Copy link
Member

Choose a reason for hiding this comment

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

Use V_PERCENTAGE instead cause you use that to check state.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

def is_closed(self):
"""Return True if cover is closed."""
set_req = self.gateway.const.SetReq
return self._values.get(set_req.V_PERCENTAGE) == '0'
Copy link
Member

Choose a reason for hiding this comment

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

Compare to 0 ie an integer.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

for value_type, value in child.values.items():
_LOGGER.debug(
'%s: value_type %s, value = %s', self._name, value_type, value)
self._values[value_type] = value
Copy link
Member

Choose a reason for hiding this comment

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

Check for V_PERCENTAGE and force that value to an integer.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

@OttoWinter
Copy link
Member Author

My problem with set_cover_position was that in the home-assistant webinterface it would show a slider for the cover position even though it was not supported by my MySensors node (I'm using end-stoppers, so setting the position with percentages is not possible with my setup).

I don't know why/when this slider shows up, but I suspect it is because the set_cover_position function exists in the MySensorsCover class. Since I wasn't able to find a way to get around this issue (by manually checking the node whether it supports setting the cover position with percentages), I dropped the method.

Maybe you have an idea how to solve this?

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.

You made a good point. I think we can solve it and support both devices with set position and without, by adding V_STATUS as a possible state report. The user has to then decide to either use V_PERCENTAGE or V_STATUS as value type for reporting state.

It's the property current_position that makes the position slider show or not. If the former is None the slider is not shown.

pres = gateway.const.Presentation
set_req = gateway.const.SetReq
map_sv_types = {
pres.S_COVER: [set_req.V_PERCENTAGE],
Copy link
Member

Choose a reason for hiding this comment

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

Add V_STATUS.

for value_type, value in child.values.items():
_LOGGER.debug(
'%s: value_type %s, value = %s', self._name, value_type, value)
if value_type == set_req.V_PERCENTAGE:
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 check and behavior to the update method in MysensorsDeviceEntity in the mysensors component, but use V_DIMMER instead to don't break version 1.4. Then you don't need to overwrite update here.

def is_closed(self):
"""Return True if cover is closed."""
set_req = self.gateway.const.SetReq
return self._values.get(set_req.V_PERCENTAGE) == 0
Copy link
Member

Choose a reason for hiding this comment

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

Check if V_PERCENTAGE is in self._values, if so return as before, if not fall back to get V_STATUS and compare that to STATE_OFF.

self.node_id, self.child_id, set_req.V_UP, 1)
if self.gateway.optimistic:
# Optimistically assume that cover has changed state.
self._values[set_req.V_PERCENTAGE] = 100
Copy link
Member

Choose a reason for hiding this comment

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

Check for V_PERCENTAGE, before setting it. Add a check for V_STATUS and set that if present.

self.node_id, self.child_id, set_req.V_DOWN, 1)
if self.gateway.optimistic:
# Optimistically assume that cover has changed state.
self._values[set_req.V_PERCENTAGE] = 0
Copy link
Member

Choose a reason for hiding this comment

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

Same as above.

@OttoWinter
Copy link
Member Author

As V_PERCENTAGE is just an alias for V_DIMMER, just as V_STATUS is an alias for V_LIGHT, theoretically MySensors v1.4 could be supported, but the value_type names wouldn't be very appropriate.

Should the version check (if float(gateway.protocol_version) < 1.5: continue) be replaced by

if float(gateway.protocol_version) >= 1.5:
    map_sv_types.update({
        pres.S_COVER: [set_req.V_DIMMER, set_req.V_LIGHT],
    })

?

@MartinHjelmare
Copy link
Member

We could make it easy for us and just use the old types, V_DIMMER and V_LIGHT, and remove any specific version check. Downside is that if the old types are removed from future mysensors versions we'll have to update the code to not break. I suggest doing it like this:

pres = gateway.const.Presentation
set_req = gateway.const.SetReq
map_sv_types = {
    pres.S_COVER: [set_req.V_DIMMER, set_req.V_LIGHT],
}
if float(gateway.protocol_version) >= 1.5:
    map_sv_types.update({
        pres.S_COVER: [set_req.V_PERCENTAGE, set_req.V_STATUS],
    })

@@ -337,7 +338,8 @@ def update(self):
_LOGGER.debug(
"%s: value_type %s, value = %s", self._name, value_type, value)
if value_type in (set_req.V_ARMED, set_req.V_LIGHT,
set_req.V_LOCK_STATUS, set_req.V_TRIPPED):
set_req.V_LOCK_STATUS, set_req.V_TRIPPED,
set_req.V_DIMMER):
Copy link
Member
@MartinHjelmare MartinHjelmare Sep 25, 2016

Choose a reason for hiding this comment

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

This should not be here, but in a separate check. The value for V_DIMMER should just be forced to an int, not changed to a home assistant state. Use an elif statement.

Copy link
Member Author

Choose a reason for hiding this comment

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

My bad. Must have overlooked that.

`V_PERCENTAGE` and `V_DIMMER` are aliases just like `V_STATUS` and
`V_LIGHT`, so the code inside `MySensorsCover` doesn’t need to be
updated.
@MartinHjelmare
Copy link
Member

Sorry, I forgot about all the rest of the types in the device class, V_PERCENTAGE and V_STATUS. We don't have access to those when specifying version 1.4 in the config, so now we either have to check for both old types, V_DIMMER and V_LIGHT and new types, V_PERCENTAGE and V_STATUS, at all the places we access the types, or we scrap trying to be portable. If we still want to port this to version 1.4 it might be easiest still just to use the old types everywhere, since they are aliases for the new types.

Sorry for going back and forth. What do you think?

@OttoWinter
Copy link
Member Author

Not a problem. I wasn't aware the v1.5 SetReq is not available within a v1.4 gateway, but it makes sense now.

I think using the old V_TYPES in code for compatibility's sake is just fine.

@MartinHjelmare
Copy link
Member

Unrelated failure of flaky test. I'll close and reopen to rerun Travis.

@MartinHjelmare
Copy link
Member

@Streberpower If you're happy, I'm happy now. 🐬 Ok, to merge?

@OttoWinter
Copy link
Member Author

Great, yes.

@MartinHjelmare
Copy link
Member

I talked with @balloob and we said that we'll hold on merging new features until after 0.29. Hopefully that can go out soon. There's an issue with segfaults that is holding it up.

@sytone
Copy link
Contributor
sytone commented Sep 26, 2016

Can you do a exists checks on the old types and if not there use the new?

Sent from Outlook for iPhone

On Sun, Sep 25, 2016 at 2:25 PM -0700, "Martin Hjelmare" notifications@github.com wrote:

We could make it easy for us and just use the old types, V_DIMMER and V_LIGHT, and remove any specific version check. Downside is that if the old types are removed from future mysensors versions we'll have to update the code to not break. I suggest doing it like this:

pres = gateway.const.Presentation
set_req = gateway.const.SetReq
map_sv_types = {
    pres.S_COVER: [set_req.V_DIMMER, set_req.V_LIGHT],
}
if float(gateway.protocol_version) >= 1.5:
    map_sv_types.update({
        pres.S_COVER: [set_req.V_PERCENTAGE, set_req.V_STATUS],
    })

You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
#3512 (comment)

@OttoWinter
Copy link
Member Author
OttoWinter commented Sep 26, 2016

Then you'd have to check which one of the V_TYPES (V_DIMMER or V_PERCENTAGE) is available in the MySensorsCover class too, which would just be a mess.

For example, consider the is_closed property. Right now it is

def is_closed(self):
    """Return True if cover is closed."""
    set_req = self.gateway.const.SetReq
    if set_req.V_DIMMER in self._values:
        return self._values.get(set_req.V_DIMMER) == 0
    else:
        return self._values.get(set_req.V_LIGHT) == STATE_OFF

But if one were checking which V_TYPE is defined, it'd be something along the lines of

def is_closed(self):
    """Return True if cover is closed."""
    set_req = self.gateway.const.SetReq
    if set_req.V_DIMMER in self._values:
        try:
            return self._values.get(set_req.V_DIMMER) == 0
        except AttributeError:
            return self._values.get(set_req.V_PERCENTAGE) == 0
    else:
        try:
            return self._values.get(set_req.V_LIGHT) == STATE_OFF
        except AttributeError:
            return self._values.get(set_req.V_STATUS) == STATE_OFF

Why bother? MySensors probably won't drop the old V_TYPES anytime soon since there's no real cost in maintaining these and many tutorials out there use the old ones. And if MySensors do, it would be an easy fix anyway. Home Assistant is already using the old V_TYPE all around the code base.

@MartinHjelmare MartinHjelmare merged commit d5f8aa5 into home-assistant:dev Sep 30, 2016
@home-assistant home-assistant locked and limited conversation to collaborators Mar 17, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants
0