-
-
Notifications
You must be signed in to change notification settings - Fork 38.3k
Create zwave devices on OZW thread and only add them during discovery #6096
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
Changes from 3 commits
9b09960
5a247eb
d277e9c
4660b8e
61a3c19
0ea85b8
b823d08
456eabc
2fab8ff
cf67e77
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,28 +52,31 @@ def setup_platform(hass, config, add_devices, discovery_info=None): | |
| """Find and add Z-Wave lights.""" | ||
| if discovery_info is None or zwave.NETWORK is None: | ||
| return | ||
| node = zwave.NETWORK.nodes[discovery_info[zwave.const.ATTR_NODE_ID]] | ||
| value = node.values[discovery_info[zwave.const.ATTR_VALUE_ID]] | ||
| add_devices( | ||
| [zwave.get_device(hass, discovery_info[zwave.const.DISCOVERY_DEVICE])]) | ||
|
|
||
|
|
||
| def get_device(node, value, node_config, **kwargs): | ||
| """Create zwave entity device.""" | ||
| name = '{}.{}'.format(DOMAIN, zwave.object_id(value)) | ||
| node_config = hass.data[zwave.DATA_DEVICE_CONFIG].get(name) | ||
| refresh = node_config.get(zwave.CONF_REFRESH_VALUE) | ||
| delay = node_config.get(zwave.CONF_REFRESH_DELAY) | ||
| _LOGGER.debug('name=%s node_config=%s CONF_REFRESH_VALUE=%s' | ||
| ' CONF_REFRESH_DELAY=%s', name, node_config, | ||
| refresh, delay) | ||
| if value.command_class != zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (for a future PR) Should this filtering happening inside these methods or should
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some filtering can be removed as it is already done in component. I'll look into it in another PR |
||
| return | ||
| return None | ||
| if value.type != zwave.const.TYPE_BYTE: | ||
| return | ||
| return None | ||
| if value.genre != zwave.const.GENRE_USER: | ||
| return | ||
| return None | ||
|
|
||
| value.set_change_verified(False) | ||
|
|
||
| if node.has_command_class(zwave.const.COMMAND_CLASS_SWITCH_COLOR): | ||
| add_devices([ZwaveColorLight(value, refresh, delay)]) | ||
| return ZwaveColorLight(value, refresh, delay) | ||
| else: | ||
| add_devices([ZwaveDimmer(value, refresh, delay)]) | ||
| return ZwaveDimmer(value, refresh, delay) | ||
|
|
||
|
|
||
| def brightness_state(value): | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -125,9 +125,12 @@ def setup_platform(hass, config, add_devices, discovery_info=None): | |
| if discovery_info is None or zwave.NETWORK is None: | ||
| return | ||
|
|
||
| node = zwave.NETWORK.nodes[discovery_info[zwave.const.ATTR_NODE_ID]] | ||
| value = node.values[discovery_info[zwave.const.ATTR_VALUE_ID]] | ||
| add_devices( | ||
| [zwave.get_device(hass, discovery_info[zwave.const.DISCOVERY_DEVICE])]) | ||
|
|
||
|
|
||
| def get_device(hass, node, value, **kwargs): | ||
| """Create zwave entity device.""" | ||
| descriptions = load_yaml_config_file( | ||
| path.join(path.dirname(__file__), 'services.yaml')) | ||
|
|
||
|
|
@@ -182,11 +185,11 @@ def clear_usercode(service): | |
| break | ||
|
|
||
| if value.command_class != zwave.const.COMMAND_CLASS_DOOR_LOCK: | ||
| return | ||
| return None | ||
| if value.type != zwave.const.TYPE_BOOL: | ||
| return | ||
| return None | ||
| if value.genre != zwave.const.GENRE_USER: | ||
| return | ||
| return None | ||
| if node.has_command_class(zwave.const.COMMAND_CLASS_USER_CODE): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Registering these services should stay in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They are registered conditionally by accessing |
||
| hass.services.register(DOMAIN, | ||
| SERVICE_SET_USERCODE, | ||
|
|
@@ -204,7 +207,7 @@ def clear_usercode(service): | |
| descriptions.get(SERVICE_CLEAR_USERCODE), | ||
| schema=CLEAR_USERCODE_SCHEMA) | ||
| value.set_change_verified(False) | ||
| add_devices([ZwaveLock(value)]) | ||
| return ZwaveLock(value) | ||
|
|
||
|
|
||
| class ZwaveLock(zwave.ZWaveDeviceEntity, LockDevice): | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,8 @@ | |
|
|
||
| import voluptuous as vol | ||
|
|
||
| from homeassistant.core import callback | ||
| from homeassistant.loader import get_platform | ||
| from homeassistant.helpers import discovery | ||
| from homeassistant.const import ( | ||
| ATTR_BATTERY_LEVEL, ATTR_LOCATION, ATTR_ENTITY_ID, ATTR_WAKEUP, | ||
|
|
@@ -54,7 +56,11 @@ | |
| DEFAULT_CONF_REFRESH_DELAY = 2 | ||
| DOMAIN = 'zwave' | ||
|
|
||
| DATA_ZWAVE_DICT = 'zwave_devices' | ||
|
|
||
| NETWORK = None | ||
|
|
||
|
|
||
| DATA_DEVICE_CONFIG = 'zwave_device_config' | ||
|
|
||
| # List of tuple (DOMAIN, discovered service, supported command classes, | ||
|
|
@@ -264,6 +270,11 @@ def get_config_value(node, value_index, tries=5): | |
| return None | ||
|
|
||
|
|
||
| def get_device(hass, dict_id): | ||
| """Return Zwave Entity device.""" | ||
| return hass.data[DATA_ZWAVE_DICT].pop(dict_id) | ||
|
|
||
|
|
||
| # pylint: disable=R0914 | ||
| def setup(hass, config): | ||
| """Setup Z-Wave. | ||
|
|
@@ -310,6 +321,7 @@ def setup(hass, config): | |
| options.lock() | ||
|
|
||
| NETWORK = ZWaveNetwork(options, autostart=False) | ||
| hass.data[DATA_ZWAVE_DICT] = {} | ||
|
|
||
| if use_debug: | ||
| def log_all(signal, value=None): | ||
|
|
@@ -399,11 +411,20 @@ def value_added(node, value): | |
| value.enable_poll(polling_intensity) | ||
| else: | ||
| value.disable_poll() | ||
| platform = get_platform(component, DOMAIN) | ||
| device = platform.get_device( | ||
| node=node, value=value, node_config=node_config, hass=hass) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can move I am not a big fan of using There is no
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Climate needs hass to pull the default units.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also most platforms don't need all 4 - won't it look better if each one would "declare" only what it needs? |
||
| if device: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use a guard clause. if not device:
return
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
| dict_id = value.value_id | ||
|
|
||
| @callback | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When this was a callback it was never executed |
||
| def discover_device(component, device, dict_id): | ||
| """Put device in a dictionary and call discovery on it.""" | ||
| hass.data[DATA_ZWAVE_DICT][dict_id] = device | ||
| discovery.load_platform(hass, component, DOMAIN, { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should probably use the async equivalent here, since we're already in the event loop at this point. No sense in creating a new job: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/helpers/discovery.py#L136 There's nothing waiting for discover_device to return.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
| const.DISCOVERY_DEVICE: dict_id}, config) | ||
|
|
||
| discovery.load_platform(hass, component, DOMAIN, { | ||
| const.ATTR_NODE_ID: node.node_id, | ||
| const.ATTR_VALUE_ID: value.value_id, | ||
| }, config) | ||
| hass.add_job(discover_device, component, device, dict_id) | ||
|
|
||
| def scene_activated(node, scene_id): | ||
| """Called when a scene is activated on any node in the network.""" | ||
|
|
@@ -694,7 +715,10 @@ def value_changed(self, value): | |
| """Called when a value for this entity's node has changed.""" | ||
| self._update_attributes() | ||
| self.update_properties() | ||
| self.schedule_update_ha_state() | ||
| # If value changed after device was createed but before setup_platform | ||
| # was called - skip updating state. | ||
| if self.hass: | ||
| self.schedule_update_ha_state() | ||
|
|
||
| def _update_attributes(self): | ||
| """Update the node attributes. May only be used inside callback.""" | ||
|
|
||
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 think that you can make a generic setup that you just import for each platform. We should make it async for improved speed:
(to be placed in
zwave/__init__.py)In the case of the lock component, you could then wrap this method and register the services.