diff --git a/homeassistant/components/zha/light.py b/homeassistant/components/zha/light.py
index efa6f679ae8fa6531f927d9e001f6acecef97b49..740d67db1bd282189ca3099fe17b881fee4efa16 100644
--- a/homeassistant/components/zha/light.py
+++ b/homeassistant/components/zha/light.py
@@ -20,7 +20,7 @@ _LOGGER = logging.getLogger(__name__)
 
 DEPENDENCIES = ['zha']
 
-DEFAULT_DURATION = 0.5
+DEFAULT_DURATION = 5
 
 CAPABILITIES_COLOR_XY = 0x08
 CAPABILITIES_COLOR_TEMP = 0x10
@@ -110,8 +110,13 @@ class Light(ZhaEntity, light.Light):
         return self.state_attributes
 
     def set_level(self, value):
-        """Set the brightness of this light between 0..255."""
-        value = max(0, min(255, value))
+        """Set the brightness of this light between 0..254.
+
+        brightness level 255 is a special value instructing the device to come
+        on at `on_level` Zigbee attribute value, regardless of the last set
+        level
+        """
+        value = max(0, min(254, value))
         self._brightness = value
         self.async_schedule_update_ha_state()
 
@@ -146,8 +151,31 @@ class Light(ZhaEntity, light.Light):
 
     async def async_turn_on(self, **kwargs):
         """Turn the entity on."""
-        duration = kwargs.get(light.ATTR_TRANSITION, DEFAULT_DURATION)
-        duration = duration * 10  # tenths of s
+        transition = kwargs.get(light.ATTR_TRANSITION)
+        duration = transition * 10 if transition else DEFAULT_DURATION
+        brightness = kwargs.get(light.ATTR_BRIGHTNESS)
+
+        if (brightness is not None or transition) and \
+                self._supported_features & light.SUPPORT_BRIGHTNESS:
+            if brightness is not None:
+                level = min(254, brightness)
+            else:
+                level = self._brightness or 254
+            success = await self._level_channel.move_to_level_with_on_off(
+                level,
+                duration
+            )
+            if not success:
+                return
+            self._state = bool(level)
+            if level:
+                self._brightness = level
+
+        if brightness is None or brightness:
+            success = await self._on_off_channel.on()
+            if not success:
+                return
+            self._state = True
 
         if light.ATTR_COLOR_TEMP in kwargs and \
                 self.supported_features & light.SUPPORT_COLOR_TEMP:
@@ -171,32 +199,12 @@ class Light(ZhaEntity, light.Light):
                 return
             self._hs_color = hs_color
 
-        if self._brightness is not None:
-            brightness = kwargs.get(
-                light.ATTR_BRIGHTNESS, self._brightness or 255)
-            success = await self._level_channel.move_to_level_with_on_off(
-                brightness,
-                duration
-            )
-            if not success:
-                return
-            self._state = True
-            self._brightness = brightness
-            self.async_schedule_update_ha_state()
-            return
-
-        success = await self._on_off_channel.on()
-        if not success:
-            return
-
-        self._state = True
         self.async_schedule_update_ha_state()
 
     async def async_turn_off(self, **kwargs):
         """Turn the entity off."""
         duration = kwargs.get(light.ATTR_TRANSITION)
         supports_level = self.supported_features & light.SUPPORT_BRIGHTNESS
-        success = None
         if duration and supports_level:
             success = await self._level_channel.move_to_level_with_on_off(
                 0,
diff --git a/tests/components/zha/test_light.py b/tests/components/zha/test_light.py
index 38d7caedaad58060226c240acfea40168555076c..0ccad52d6aa3e32ebdd9a034740a5072118e15a7 100644
--- a/tests/components/zha/test_light.py
+++ b/tests/components/zha/test_light.py
@@ -1,20 +1,24 @@
 """Test zha light."""
-from unittest.mock import call, patch
+import asyncio
+from unittest.mock import MagicMock, call, patch, sentinel
+
 from homeassistant.components.light import DOMAIN
-from homeassistant.const import STATE_ON, STATE_OFF, STATE_UNAVAILABLE
-from tests.common import mock_coro
+from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNAVAILABLE
+
 from .common import (
-    async_init_zigpy_device, make_attribute, make_entity_id,
-    async_test_device_join, async_enable_traffic
-)
+    async_enable_traffic, async_init_zigpy_device, async_test_device_join,
+    make_attribute, make_entity_id)
+
+from tests.common import mock_coro
 
 ON = 1
 OFF = 0
 
 
-async def test_light(hass, config_entry, zha_gateway):
+async def test_light(hass, config_entry, zha_gateway, monkeypatch):
     """Test zha light platform."""
     from zigpy.zcl.clusters.general import OnOff, LevelControl, Basic
+    from zigpy.zcl.foundation import Status
     from zigpy.profiles.zha import DeviceType
 
     # create zigpy devices
@@ -52,6 +56,12 @@ async def test_light(hass, config_entry, zha_gateway):
     # dimmable light
     level_device_on_off_cluster = zigpy_device_level.endpoints.get(1).on_off
     level_device_level_cluster = zigpy_device_level.endpoints.get(1).level
+    on_off_mock = MagicMock(side_effect=asyncio.coroutine(MagicMock(
+        return_value=(sentinel.data, Status.SUCCESS))))
+    level_mock = MagicMock(side_effect=asyncio.coroutine(MagicMock(
+        return_value=(sentinel.data, Status.SUCCESS))))
+    monkeypatch.setattr(level_device_on_off_cluster, 'request', on_off_mock)
+    monkeypatch.setattr(level_device_level_cluster, 'request', level_mock)
     level_entity_id = make_entity_id(DOMAIN, zigpy_device_level,
                                      level_device_on_off_cluster,
                                      use_suffix=False)
@@ -81,7 +91,8 @@ async def test_light(hass, config_entry, zha_gateway):
         hass, on_off_device_on_off_cluster, on_off_entity_id)
 
     await async_test_level_on_off_from_hass(
-        hass, level_device_on_off_cluster, level_entity_id)
+        hass, level_device_on_off_cluster, level_device_level_cluster,
+        level_entity_id)
 
     # test turning the lights on and off from the light
     await async_test_on_from_light(
@@ -131,7 +142,7 @@ async def async_test_on_off_from_hass(hass, cluster, entity_id):
         await hass.services.async_call(DOMAIN, 'turn_on', {
             'entity_id': entity_id
         }, blocking=True)
-        assert len(cluster.request.mock_calls) == 1
+        assert cluster.request.call_count == 1
         assert cluster.request.call_args == call(
             False, ON, (), expect_reply=True, manufacturer=None)
 
@@ -148,28 +159,52 @@ async def async_test_off_from_hass(hass, cluster, entity_id):
         await hass.services.async_call(DOMAIN, 'turn_off', {
             'entity_id': entity_id
         }, blocking=True)
-        assert len(cluster.request.mock_calls) == 1
+        assert cluster.request.call_count == 1
         assert cluster.request.call_args == call(
             False, OFF, (), expect_reply=True, manufacturer=None)
 
 
-async def async_test_level_on_off_from_hass(hass, cluster, entity_id):
+async def async_test_level_on_off_from_hass(hass, on_off_cluster,
+                                            level_cluster, entity_id):
     """Test on off functionality from hass."""
     from zigpy import types
-    from zigpy.zcl.foundation import Status
-    with patch(
-            'zigpy.zcl.Cluster.request',
-            return_value=mock_coro([Status.SUCCESS, Status.SUCCESS])):
-        # turn on via UI
-        await hass.services.async_call(DOMAIN, 'turn_on', {
-            'entity_id': entity_id
-        }, blocking=True)
-        assert len(cluster.request.mock_calls) == 1
-        assert cluster.request.call_args == call(
-            False, 4, (types.uint8_t, types.uint16_t), 255, 5.0,
-            expect_reply=True, manufacturer=None)
-
-    await async_test_off_from_hass(hass, cluster, entity_id)
+    # turn on via UI
+    await hass.services.async_call(DOMAIN, 'turn_on', {'entity_id': entity_id},
+                                   blocking=True)
+    assert on_off_cluster.request.call_count == 1
+    assert level_cluster.request.call_count == 0
+    assert on_off_cluster.request.call_args == call(
+        False, 1, (), expect_reply=True, manufacturer=None)
+    on_off_cluster.request.reset_mock()
+    level_cluster.request.reset_mock()
+
+    await hass.services.async_call(DOMAIN, 'turn_on',
+                                   {'entity_id': entity_id, 'transition': 10},
+                                   blocking=True)
+    assert on_off_cluster.request.call_count == 1
+    assert level_cluster.request.call_count == 1
+    assert on_off_cluster.request.call_args == call(
+        False, 1, (), expect_reply=True, manufacturer=None)
+    assert level_cluster.request.call_args == call(
+        False, 4, (types.uint8_t, types.uint16_t), 254, 100.0,
+        expect_reply=True, manufacturer=None)
+    on_off_cluster.request.reset_mock()
+    level_cluster.request.reset_mock()
+
+    await hass.services.async_call(DOMAIN, 'turn_on',
+                                   {'entity_id': entity_id, 'brightness': 10},
+                                   blocking=True)
+    assert on_off_cluster.request.call_count == 1
+    assert level_cluster.request.call_count == 1
+    assert on_off_cluster.request.call_args == call(
+        False, 1, (), expect_reply=True, manufacturer=None)
+    assert level_cluster.request.call_args == call(
+        False, 4, (types.uint8_t, types.uint16_t), 10, 5.0,
+        expect_reply=True, manufacturer=None)
+    on_off_cluster.request.reset_mock()
+    level_cluster.request.reset_mock()
+
+    await async_test_off_from_hass(hass, on_off_cluster, entity_id)
 
 
 async def async_test_dimmer_from_light(hass, cluster, entity_id,