diff --git a/homeassistant/components/zwave/__init__.py b/homeassistant/components/zwave/__init__.py
index a5a460d129e29b62c4a69b7b7a277c505a4418be..b32a76be40b1a8f7a3e71b9fad32f682aa0531ed 100644
--- a/homeassistant/components/zwave/__init__.py
+++ b/homeassistant/components/zwave/__init__.py
@@ -68,12 +68,14 @@ SUPPORTED_PLATFORMS = ['binary_sensor', 'climate', 'cover', 'fan',
 RENAME_NODE_SCHEMA = vol.Schema({
     vol.Required(const.ATTR_NODE_ID): vol.Coerce(int),
     vol.Required(const.ATTR_NAME): cv.string,
+    vol.Optional(const.ATTR_UPDATE_IDS, default=False): cv.boolean,
 })
 
 RENAME_VALUE_SCHEMA = vol.Schema({
     vol.Required(const.ATTR_NODE_ID): vol.Coerce(int),
     vol.Required(const.ATTR_VALUE_ID): vol.Coerce(int),
     vol.Required(const.ATTR_NAME): cv.string,
+    vol.Optional(const.ATTR_UPDATE_IDS, default=False): cv.boolean,
 })
 
 SET_CONFIG_PARAMETER_SCHEMA = vol.Schema({
@@ -389,8 +391,7 @@ async def async_setup_entry(hass, config_entry):
                 entity.node_id, sec)
             hass.async_add_job(_add_node_to_component)
 
-        hass.add_job(check_has_unique_id, entity, _on_ready, _on_timeout,
-                     hass.loop)
+        hass.add_job(check_has_unique_id, entity, _on_ready, _on_timeout)
 
     def node_removed(node):
         node_id = node.node_id
@@ -491,6 +492,7 @@ async def async_setup_entry(hass, config_entry):
         if hass.state == CoreState.running:
             hass.bus.fire(const.EVENT_NETWORK_STOP)
 
+    @callback
     def rename_node(service):
         """Rename a node."""
         node_id = service.data.get(const.ATTR_NODE_ID)
@@ -499,7 +501,19 @@ async def async_setup_entry(hass, config_entry):
         node.name = name
         _LOGGER.info(
             "Renamed Z-Wave node %d to %s", node_id, name)
+        update_ids = service.data.get(const.ATTR_UPDATE_IDS)
+        # We want to rename the device, the node entity,
+        # and all the contained entities
+        node_key = 'node-{}'.format(node_id)
+        entity = hass.data[DATA_DEVICES][node_key]
+        hass.async_create_task(entity.node_renamed(update_ids))
+        for key in list(hass.data[DATA_DEVICES]):
+            if not key.startswith('{}-'.format(node_id)):
+                continue
+            entity = hass.data[DATA_DEVICES][key]
+            hass.async_create_task(entity.value_renamed(update_ids))
 
+    @callback
     def rename_value(service):
         """Rename a node value."""
         node_id = service.data.get(const.ATTR_NODE_ID)
@@ -511,6 +525,10 @@ async def async_setup_entry(hass, config_entry):
         _LOGGER.info(
             "Renamed Z-Wave value (Node %d Value %d) to %s",
             node_id, value_id, name)
+        update_ids = service.data.get(const.ATTR_UPDATE_IDS)
+        value_key = '{}-{}'.format(node_id, value_id)
+        entity = hass.data[DATA_DEVICES][value_key]
+        hass.async_create_task(entity.value_renamed(update_ids))
 
     def set_poll_intensity(service):
         """Set the polling intensity of a node value."""
@@ -996,7 +1014,7 @@ class ZWaveDeviceEntityValues():
             self._hass.add_job(discover_device, component, device)
         else:
             self._hass.add_job(check_has_unique_id, device, _on_ready,
-                               _on_timeout, self._hass.loop)
+                               _on_timeout)
 
 
 class ZWaveDeviceEntity(ZWaveBaseEntity):
@@ -1034,6 +1052,25 @@ class ZWaveDeviceEntity(ZWaveBaseEntity):
         self.update_properties()
         self.maybe_schedule_update()
 
+    async def value_renamed(self, update_ids=False):
+        """Rename the node and update any IDs."""
+        self._name = _value_name(self.values.primary)
+        if update_ids:
+            # Update entity ID.
+            ent_reg = await async_get_registry(self.hass)
+            new_entity_id = ent_reg.async_generate_entity_id(
+                self.platform.domain,
+                self._name,
+                self.platform.entities.keys() - {self.entity_id})
+            if new_entity_id != self.entity_id:
+                # Don't change the name attribute, it will be None unless
+                # customised and if it's been customised, keep the
+                # customisation.
+                ent_reg.async_update_entity(
+                    self.entity_id, new_entity_id=new_entity_id)
+                return
+        self.async_schedule_update_ha_state()
+
     async def async_added_to_hass(self):
         """Add device to dict."""
         async_dispatcher_connect(
diff --git a/homeassistant/components/zwave/const.py b/homeassistant/components/zwave/const.py
index 67b5341a4e60a2f8c178f4a272e4d23e5aff21ee..5a09b54235de0835146c5e4b938ce9a6203897e6 100644
--- a/homeassistant/components/zwave/const.py
+++ b/homeassistant/components/zwave/const.py
@@ -19,6 +19,7 @@ ATTR_CONFIG_VALUE = "value"
 ATTR_POLL_INTENSITY = "poll_intensity"
 ATTR_VALUE_INDEX = "value_index"
 ATTR_VALUE_INSTANCE = "value_instance"
+ATTR_UPDATE_IDS = 'update_ids'
 NETWORK_READY_WAIT_SECS = 300
 NODE_READY_WAIT_SECS = 30
 
diff --git a/homeassistant/components/zwave/node_entity.py b/homeassistant/components/zwave/node_entity.py
index 3bba18f5c020588cc80da353126c8a61b0eaaeef..9a721ecf2d7609ccb99ce6bf9fd1c19509adb2ce 100644
--- a/homeassistant/components/zwave/node_entity.py
+++ b/homeassistant/components/zwave/node_entity.py
@@ -1,9 +1,13 @@
 """Entity class that represents Z-Wave node."""
 import logging
+from itertools import count
 
 from homeassistant.core import callback
-from homeassistant.const import ATTR_BATTERY_LEVEL, ATTR_WAKEUP, ATTR_ENTITY_ID
+from homeassistant.const import (
+    ATTR_BATTERY_LEVEL, ATTR_WAKEUP, ATTR_ENTITY_ID)
 from homeassistant.helpers.entity_registry import async_get_registry
+from homeassistant.helpers.device_registry import (
+    async_get_registry as get_dev_reg)
 from homeassistant.helpers.entity import Entity
 
 from .const import (
@@ -192,6 +196,42 @@ class ZWaveNodeEntity(ZWaveBaseEntity):
 
         self.maybe_schedule_update()
 
+    async def node_renamed(self, update_ids=False):
+        """Rename the node and update any IDs."""
+        self._name = node_name(self.node)
+        # Set the name in the devices. If they're customised
+        # the customisation will not be stored as name and will stick.
+        dev_reg = await get_dev_reg(self.hass)
+        device = dev_reg.async_get_device(
+            identifiers={(DOMAIN, self.node_id), },
+            connections=set())
+        dev_reg.async_update_device(device.id, name=self._name)
+        # update sub-devices too
+        for i in count(2):
+            identifier = (DOMAIN, self.node_id, i)
+            device = dev_reg.async_get_device(
+                identifiers={identifier, },
+                connections=set())
+            if not device:
+                break
+            new_name = "{} ({})".format(self._name, i)
+            dev_reg.async_update_device(device.id, name=new_name)
+
+        # Update entity ID.
+        if update_ids:
+            ent_reg = await async_get_registry(self.hass)
+            new_entity_id = ent_reg.async_generate_entity_id(
+                DOMAIN, self._name,
+                self.platform.entities.keys() - {self.entity_id})
+            if new_entity_id != self.entity_id:
+                # Don't change the name attribute, it will be None unless
+                # customised and if it's been customised, keep the
+                # customisation.
+                ent_reg.async_update_entity(
+                    self.entity_id, new_entity_id=new_entity_id)
+                return
+        self.async_schedule_update_ha_state()
+
     def network_node_event(self, node, value):
         """Handle a node activated event on the network."""
         if node.node_id == self.node.node_id:
diff --git a/homeassistant/components/zwave/services.yaml b/homeassistant/components/zwave/services.yaml
index 83e6ea2533b18094445f2782fb86d61af5954bd9..37b1223275934ee93dca7a72e5a4da15bbffa666 100644
--- a/homeassistant/components/zwave/services.yaml
+++ b/homeassistant/components/zwave/services.yaml
@@ -168,6 +168,9 @@ rename_node:
     node_id:
       description: ID of the node to rename.
       example: 10
+    update_ids:
+      description: (optional) Rename the entity IDs for entities of this node.
+      example: True
     name:
       description: New Name
       example: 'kitchen'
@@ -181,6 +184,9 @@ rename_value:
     value_id:
       description: ID of the value to rename.
       example: 72037594255792737
+    update_ids:
+      description: (optional) Update the entity ID for this value's entity.
+      example: True
     name:
       description: New Name
       example: 'Luminosity'
diff --git a/homeassistant/components/zwave/util.py b/homeassistant/components/zwave/util.py
index 312d72575a94aeed0e5b634155dabf9f3be28387..a3b6d9a956d2679e81fce09c200ed5977a028282 100644
--- a/homeassistant/components/zwave/util.py
+++ b/homeassistant/components/zwave/util.py
@@ -74,7 +74,7 @@ def node_name(node):
     return 'Unknown Node {}'.format(node.node_id)
 
 
-async def check_has_unique_id(entity, ready_callback, timeout_callback, loop):
+async def check_has_unique_id(entity, ready_callback, timeout_callback):
     """Wait for entity to have unique_id."""
     start_time = dt_util.utcnow()
     while True:
@@ -86,7 +86,7 @@ async def check_has_unique_id(entity, ready_callback, timeout_callback, loop):
             # Wait up to NODE_READY_WAIT_SECS seconds for unique_id to appear.
             timeout_callback(waited)
             return
-        await asyncio.sleep(1, loop=loop)
+        await asyncio.sleep(1)
 
 
 def is_node_parsed(node):
diff --git a/homeassistant/helpers/device_registry.py b/homeassistant/helpers/device_registry.py
index 77c788035abb3f9b7ea07f567979edc8263631c5..8f53850b6191115411f9dba1d12ab723b6ff6537 100644
--- a/homeassistant/helpers/device_registry.py
+++ b/homeassistant/helpers/device_registry.py
@@ -136,11 +136,13 @@ class DeviceRegistry:
 
     @callback
     def async_update_device(
-            self, device_id, *, area_id=_UNDEF, name_by_user=_UNDEF,
+            self, device_id, *, area_id=_UNDEF,
+            name=_UNDEF, name_by_user=_UNDEF,
             new_identifiers=_UNDEF):
         """Update properties of a device."""
         return self._async_update_device(
-            device_id, area_id=area_id, name_by_user=name_by_user,
+            device_id, area_id=area_id,
+            name=name, name_by_user=name_by_user,
             new_identifiers=new_identifiers)
 
     @callback
diff --git a/tests/components/zwave/test_init.py b/tests/components/zwave/test_init.py
index 69ee7c45a9b50a592dbfe8a815e2bd860d2df777..19830b1343c93431250ea25c3cf3d7c9aafe1190 100644
--- a/tests/components/zwave/test_init.py
+++ b/tests/components/zwave/test_init.py
@@ -2,26 +2,27 @@
 import asyncio
 from collections import OrderedDict
 from datetime import datetime
+import unittest
+from unittest.mock import MagicMock, patch
+
+import pytest
 from pytz import utc
 import voluptuous as vol
 
-import unittest
-from unittest.mock import patch, MagicMock
-
 from homeassistant.bootstrap import async_setup_component
-from homeassistant.const import ATTR_ENTITY_ID, EVENT_HOMEASSISTANT_START
 from homeassistant.components import zwave
-from homeassistant.components.zwave.binary_sensor import get_device
 from homeassistant.components.zwave import (
-    const, CONFIG_SCHEMA, CONF_DEVICE_CONFIG_GLOB, DATA_NETWORK)
+    CONF_DEVICE_CONFIG_GLOB, CONFIG_SCHEMA, DATA_NETWORK, const)
+from homeassistant.components.zwave.binary_sensor import get_device
+from homeassistant.const import ATTR_ENTITY_ID, EVENT_HOMEASSISTANT_START
+from homeassistant.helpers.entity_registry import async_get_registry
+from homeassistant.helpers.device_registry import (
+    async_get_registry as get_dev_reg)
 from homeassistant.setup import setup_component
-from tests.common import mock_registry
-
-import pytest
 
 from tests.common import (
-    get_test_home_assistant, async_fire_time_changed, mock_coro)
-from tests.mock.zwave import MockNetwork, MockNode, MockValue, MockEntityValues
+    async_fire_time_changed, get_test_home_assistant, mock_coro, mock_registry)
+from tests.mock.zwave import MockEntityValues, MockNetwork, MockNode, MockValue
 
 
 async def test_valid_device_config(hass, mock_openzwave):
@@ -382,6 +383,150 @@ async def test_value_discovery(hass, mock_openzwave):
         'binary_sensor.mock_node_mock_value').state == 'off'
 
 
+async def test_value_entities(hass, mock_openzwave):
+    """Test discovery of a node."""
+    mock_receivers = {}
+
+    def mock_connect(receiver, signal, *args, **kwargs):
+        mock_receivers[signal] = receiver
+
+    with patch('pydispatch.dispatcher.connect', new=mock_connect):
+        await async_setup_component(hass, 'zwave', {'zwave': {}})
+        await hass.async_block_till_done()
+
+    zwave_network = hass.data[DATA_NETWORK]
+    zwave_network.state = MockNetwork.STATE_READY
+    hass.bus.async_fire(EVENT_HOMEASSISTANT_START)
+    await hass.async_block_till_done()
+
+    assert mock_receivers
+
+    hass.async_add_job(
+        mock_receivers[MockNetwork.SIGNAL_ALL_NODES_QUERIED])
+    node = MockNode(node_id=11, generic=const.GENERIC_TYPE_SENSOR_BINARY)
+    zwave_network.nodes = {node.node_id: node}
+    value = MockValue(
+        data=False, node=node, index=12, instance=1,
+        command_class=const.COMMAND_CLASS_SENSOR_BINARY,
+        type=const.TYPE_BOOL, genre=const.GENRE_USER)
+    node.values = {'primary': value, value.value_id: value}
+    value2 = MockValue(
+        data=False, node=node, index=12, instance=2,
+        label="Mock Value B",
+        command_class=const.COMMAND_CLASS_SENSOR_BINARY,
+        type=const.TYPE_BOOL, genre=const.GENRE_USER)
+    node.values[value2.value_id] = value2
+
+    hass.async_add_job(
+        mock_receivers[MockNetwork.SIGNAL_NODE_ADDED], node)
+    hass.async_add_job(
+        mock_receivers[MockNetwork.SIGNAL_VALUE_ADDED], node, value)
+    hass.async_add_job(
+        mock_receivers[MockNetwork.SIGNAL_VALUE_ADDED], node, value2)
+    await hass.async_block_till_done()
+
+    assert hass.states.get(
+        'binary_sensor.mock_node_mock_value').state == 'off'
+    assert hass.states.get(
+        'binary_sensor.mock_node_mock_value_b').state == 'off'
+
+    ent_reg = await async_get_registry(hass)
+    dev_reg = await get_dev_reg(hass)
+
+    entry = ent_reg.async_get('zwave.mock_node')
+    assert entry is not None
+    assert entry.unique_id == 'node-{}'.format(node.node_id)
+    node_dev_id = entry.device_id
+
+    entry = ent_reg.async_get('binary_sensor.mock_node_mock_value')
+    assert entry is not None
+    assert entry.unique_id == '{}-{}'.format(node.node_id, value.object_id)
+    assert entry.name is None
+    assert entry.device_id == node_dev_id
+
+    entry = ent_reg.async_get('binary_sensor.mock_node_mock_value_b')
+    assert entry is not None
+    assert entry.unique_id == '{}-{}'.format(node.node_id, value2.object_id)
+    assert entry.name is None
+    assert entry.device_id != node_dev_id
+    device_id_b = entry.device_id
+
+    device = dev_reg.async_get(node_dev_id)
+    assert device is not None
+    assert device.name == node.name
+    old_device = device
+
+    device = dev_reg.async_get(device_id_b)
+    assert device is not None
+    assert device.name == "{} ({})".format(node.name, value2.instance)
+
+    # test renaming without updating
+    await hass.services.async_call('zwave', 'rename_node', {
+        const.ATTR_NODE_ID: node.node_id,
+        const.ATTR_NAME: "Demo Node",
+    })
+    await hass.async_block_till_done()
+
+    assert node.name == "Demo Node"
+
+    entry = ent_reg.async_get('zwave.mock_node')
+    assert entry is not None
+
+    entry = ent_reg.async_get('binary_sensor.mock_node_mock_value')
+    assert entry is not None
+
+    entry = ent_reg.async_get('binary_sensor.mock_node_mock_value_b')
+    assert entry is not None
+
+    device = dev_reg.async_get(node_dev_id)
+    assert device is not None
+    assert device.id == old_device.id
+    assert device.name == node.name
+
+    device = dev_reg.async_get(device_id_b)
+    assert device is not None
+    assert device.name == "{} ({})".format(node.name, value2.instance)
+
+    # test renaming
+    await hass.services.async_call('zwave', 'rename_node', {
+        const.ATTR_NODE_ID: node.node_id,
+        const.ATTR_UPDATE_IDS: True,
+        const.ATTR_NAME: "New Node",
+    })
+    await hass.async_block_till_done()
+
+    assert node.name == "New Node"
+
+    entry = ent_reg.async_get('zwave.new_node')
+    assert entry is not None
+    assert entry.unique_id == 'node-{}'.format(node.node_id)
+
+    entry = ent_reg.async_get('binary_sensor.new_node_mock_value')
+    assert entry is not None
+    assert entry.unique_id == '{}-{}'.format(node.node_id, value.object_id)
+
+    device = dev_reg.async_get(node_dev_id)
+    assert device is not None
+    assert device.id == old_device.id
+    assert device.name == node.name
+
+    device = dev_reg.async_get(device_id_b)
+    assert device is not None
+    assert device.name == "{} ({})".format(node.name, value2.instance)
+
+    await hass.services.async_call('zwave', 'rename_value', {
+        const.ATTR_NODE_ID: node.node_id,
+        const.ATTR_VALUE_ID: value.object_id,
+        const.ATTR_UPDATE_IDS: True,
+        const.ATTR_NAME: "New Label",
+    })
+    await hass.async_block_till_done()
+
+    entry = ent_reg.async_get('binary_sensor.new_node_new_label')
+    assert entry is not None
+    assert entry.unique_id == '{}-{}'.format(node.node_id, value.object_id)
+
+
 async def test_value_discovery_existing_entity(hass, mock_openzwave):
     """Test discovery of a node."""
     mock_receivers = []