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

Improve service by allowing to reference entity id instead of deconz id #11862

Merged
merged 15 commits into from
Feb 14, 2018

Conversation

Kane610
Copy link
Member

@Kane610 Kane610 commented Jan 22, 2018

Description:

It is cumbersome to get ahold of the deconz_id, this allows the user to specify the entity_id instead.

Related issue (if applicable): fixes #

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

Checklist:

  • The code change is tested and works locally.

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

Copy link
Member

@balloob balloob left a comment

Choose a reason for hiding this comment

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

It's not clear to me why this is necessary to begin with?

yield from deconz.async_put_state(field, data)
entity_id = call.data.get(SERVICE_ENTITY)
data_string = call.data.get(SERVICE_DATA)
data = ast.literal_eval(data_string) # String to dict
Copy link
Member

Choose a reason for hiding this comment

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

Eval is not allowed, too dangerous.

Copy link
Member Author

Choose a reason for hiding this comment

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

Do you have suggestion about how I can get a dictionary here?

Copy link
Member Author

Choose a reason for hiding this comment

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

The Issue here is that data is expected to be json compliant, which it unfortunately isn't since it get single quotes, where as json.loads expects double quotes. So there is a translation going on from the service entry in the gui to the service in the backend; {"name": "TRADFRI motion sensor 1"} arrives as {'name': 'TRADFRI motion sensor 1'}

@@ -29,6 +30,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
if sensor and sensor.type in DECONZ_BINARY_SENSOR:
entities.append(DeconzBinarySensor(sensor))
async_add_devices(entities, True)
hass.data[DECONZ_ENTITIES] = hass.data[DECONZ_ENTITIES] + entities
Copy link
Member

Choose a reason for hiding this comment

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

This is not allowed. Main component should not have access to the entity objects.

Copy link
Member Author

Choose a reason for hiding this comment

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

I guess I could just do a translation dict between entity name and deconz id instead

@Kane610
Copy link
Member Author

Kane610 commented Jan 23, 2018

The real issue is that there is no easy way for the user to know the deconZ_id. I could add it as an attribute to each entity or do you have an alternative to how I can do this? The important thing is to help the user being able to use the service with all devices in deconz.

@Kane610
Copy link
Member Author

Kane610 commented Jan 24, 2018

@balloob I'd be happy to implement according to your wishes or redesign when your entity registry has been delivered, can we move forward with this?

@@ -37,6 +38,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
entities.append(DeconzBattery(sensor))
else:
entities.append(DeconzSensor(sensor))
#entities.append(DeconzSensor(sensor, entity_registry))

Choose a reason for hiding this comment

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

block comment should start with '# '

@@ -26,6 +26,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):

from pydeconz.sensor import DECONZ_SENSOR, SWITCH as DECONZ_REMOTE
sensors = hass.data[DECONZ_DATA].sensors
#entity_registry = hass.data[DECONZ_ENTITIES]

Choose a reason for hiding this comment

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

block comment should start with '# '

groups = list(deconz.groups.values())
lights = list(deconz.lights.values())
sensors = list(deconz.sensors.values())
devices = groups + lights + sensors
Copy link
Member

Choose a reason for hiding this comment

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

I think what you're looking for is chain, that way you don't have to create a list but can just iterate over it.

from itertools import chain

for device in chain(deconz.groups.values(), deconz.lights.values(), …):

deconz = hass.data[DOMAIN]

registry = hass.data.get(DATA_REGISTRY)
if registry.async_is_registered(entity_id):
Copy link
Member

Choose a reason for hiding this comment

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

Not needed here, just get the entry. Do make sure to use guard clause pattern:

entry = registry.async_get_entry(…)
if entry is None:
    _LOGGER.error(…)
    return

registry = hass.data.get(DATA_REGISTRY)
entity = registry.async_get_entry(entity_id)
for device in chain(
deconz.groups.values(), deconz.lights.values(), deconz.sensors.values()):

Choose a reason for hiding this comment

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

line too long (93 > 79 characters)

Copy link
Member

@balloob balloob left a comment

Choose a reason for hiding this comment

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

I'm sorry. I've thought about it more and I think that it's better to keep the Entity Registry private for now. So let have deconz keep track of unique id's.

You could do something like this fairly easy by leveraging the async_added_to_hass callback:

class DeconzLight(Light):

    @asyncio.coroutine
    def async_added_to_hass(self):
        """Called when entity added to hass."""
        self.hass.data[DATA_DECONZ_ID][self.entity_id] = self.unique_id

(self.hass and self.entity_id are guaranteed to exist when async_added_to_hass is called)

@Kane610
Copy link
Member Author

Kane610 commented Feb 13, 2018

@balloob alright, should I remove the new method for registry? Yes that was the original way I was doing it, just thought the registry would remove the need for a local registry.

@balloob
Copy link
Member

balloob commented Feb 13, 2018

I know. Sorry for not realizing this earlier.

Let's remove it.

@Kane610
Copy link
Member Author

Kane610 commented Feb 13, 2018

No worries, it is not always easy to have a plan ready for new functionality. I will change these things tonight.

import asyncio
import logging
from itertools import chain

Choose a reason for hiding this comment

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

'itertools.chain' imported but unused

import asyncio
import logging
from itertools import chain

Choose a reason for hiding this comment

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

'itertools.chain' imported but unused

@Kane610
Copy link
Member Author

Kane610 commented Feb 13, 2018

@balloob better like this?

async_add_devices(entities, True)


class DeconzBinarySensor(BinarySensorDevice):
"""Representation of a binary sensor."""

def __init__(self, sensor):
def __init__(self, hass, sensor):
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 the entity has been added to home assistant. This means you can access hass with self.hass, after the entity has been added to home assistant.

"""Set up sensor and add update callback to get data from websocket."""
self.hass = hass
Copy link
Member

Choose a reason for hiding this comment

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

Remove this.

async_add_devices(entities, True)


class DeconzLight(Light):
"""Representation of a deCONZ light."""

def __init__(self, light):
def __init__(self, hass, light):
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 the entity has been added to home assistant. This means you can access hass with self.hass, after the entity has been added to home assistant.

"""Set up light and add update callback to get data from websocket."""
self.hass = hass
Copy link
Member

Choose a reason for hiding this comment

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

Please remove.

async_add_devices(entities)


class DeconzScene(Scene):
"""Representation of a deCONZ scene."""

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

Choose a reason for hiding this comment

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

See above.

"""Set up a scene."""
self.hass = hass
Copy link
Member

Choose a reason for hiding this comment

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

See above.

async_add_devices(entities, True)


class DeconzSensor(Entity):
"""Representation of a sensor."""

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

Choose a reason for hiding this comment

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

See above.

"""Set up sensor and add update callback to get data from websocket."""
self.hass = hass
Copy link
Member

Choose a reason for hiding this comment

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

See above.

@@ -116,8 +119,9 @@ def device_state_attributes(self):
class DeconzBattery(Entity):
"""Battery class for when a device is only represented as an event."""

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

Choose a reason for hiding this comment

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

See above.

"""Register dispatcher callback for update of battery state."""
self.hass = hass
Copy link
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
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 good to me!

@Kane610
Copy link
Member Author

Kane610 commented Feb 13, 2018

Thanks @MartinHjelmare

@balloob balloob merged commit 8bff813 into home-assistant:dev Feb 14, 2018
@Kane610 Kane610 deleted the deconz-simplify-service branch February 14, 2018 17:03
@balloob balloob mentioned this pull request Feb 22, 2018
@home-assistant home-assistant locked and limited conversation to collaborators May 29, 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.

5 participants