diff --git a/.gitattributes b/.gitattributes
index 1e4e6c6a091ccb..caff2fc5c1f7a3 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -7,3 +7,4 @@
*.jpg binary
*.png binary
*.zip binary
+*.mp3 binary
diff --git a/homeassistant/components/alarm_control_panel/services.yaml b/homeassistant/components/alarm_control_panel/services.yaml
index bfd38c902d0a1b..72784c8178c15a 100644
--- a/homeassistant/components/alarm_control_panel/services.yaml
+++ b/homeassistant/components/alarm_control_panel/services.yaml
@@ -1,71 +1,71 @@
-# Describes the format for available alarm control panel services
-
-alarm_disarm:
- description: Send the alarm the command for disarm.
- fields:
- entity_id:
- description: Name of alarm control panel to disarm.
- example: 'alarm_control_panel.downstairs'
- code:
- description: An optional code to disarm the alarm control panel with.
- example: 1234
-
-alarm_arm_home:
- description: Send the alarm the command for arm home.
- fields:
- entity_id:
- description: Name of alarm control panel to arm home.
- example: 'alarm_control_panel.downstairs'
- code:
- description: An optional code to arm home the alarm control panel with.
- example: 1234
-
-alarm_arm_away:
- description: Send the alarm the command for arm away.
- fields:
- entity_id:
- description: Name of alarm control panel to arm away.
- example: 'alarm_control_panel.downstairs'
- code:
- description: An optional code to arm away the alarm control panel with.
- example: 1234
-
-alarm_arm_night:
- description: Send the alarm the command for arm night.
- fields:
- entity_id:
- description: Name of alarm control panel to arm night.
- example: 'alarm_control_panel.downstairs'
- code:
- description: An optional code to arm night the alarm control panel with.
- example: 1234
-
-alarm_trigger:
- description: Send the alarm the command for trigger.
- fields:
- entity_id:
- description: Name of alarm control panel to trigger.
- example: 'alarm_control_panel.downstairs'
- code:
- description: An optional code to trigger the alarm control panel with.
- example: 1234
-
-envisalink_alarm_keypress:
- description: Send custom keypresses to the alarm.
- fields:
- entity_id:
- description: Name of the alarm control panel to trigger.
- example: 'alarm_control_panel.downstairs'
- keypress:
- description: 'String to send to the alarm panel (1-6 characters).'
- example: '*71'
-
-alarmdecoder_alarm_toggle_chime:
- description: Send the alarm the toggle chime command.
- fields:
- entity_id:
- description: Name of the alarm control panel to trigger.
- example: 'alarm_control_panel.downstairs'
- code:
- description: A required code to toggle the alarm control panel chime with.
- example: 1234
+# Describes the format for available alarm control panel services
+
+alarm_disarm:
+ description: Send the alarm the command for disarm.
+ fields:
+ entity_id:
+ description: Name of alarm control panel to disarm.
+ example: 'alarm_control_panel.downstairs'
+ code:
+ description: An optional code to disarm the alarm control panel with.
+ example: 1234
+
+alarm_arm_home:
+ description: Send the alarm the command for arm home.
+ fields:
+ entity_id:
+ description: Name of alarm control panel to arm home.
+ example: 'alarm_control_panel.downstairs'
+ code:
+ description: An optional code to arm home the alarm control panel with.
+ example: 1234
+
+alarm_arm_away:
+ description: Send the alarm the command for arm away.
+ fields:
+ entity_id:
+ description: Name of alarm control panel to arm away.
+ example: 'alarm_control_panel.downstairs'
+ code:
+ description: An optional code to arm away the alarm control panel with.
+ example: 1234
+
+alarm_arm_night:
+ description: Send the alarm the command for arm night.
+ fields:
+ entity_id:
+ description: Name of alarm control panel to arm night.
+ example: 'alarm_control_panel.downstairs'
+ code:
+ description: An optional code to arm night the alarm control panel with.
+ example: 1234
+
+alarm_trigger:
+ description: Send the alarm the command for trigger.
+ fields:
+ entity_id:
+ description: Name of alarm control panel to trigger.
+ example: 'alarm_control_panel.downstairs'
+ code:
+ description: An optional code to trigger the alarm control panel with.
+ example: 1234
+
+envisalink_alarm_keypress:
+ description: Send custom keypresses to the alarm.
+ fields:
+ entity_id:
+ description: Name of the alarm control panel to trigger.
+ example: 'alarm_control_panel.downstairs'
+ keypress:
+ description: 'String to send to the alarm panel (1-6 characters).'
+ example: '*71'
+
+alarmdecoder_alarm_toggle_chime:
+ description: Send the alarm the toggle chime command.
+ fields:
+ entity_id:
+ description: Name of the alarm control panel to trigger.
+ example: 'alarm_control_panel.downstairs'
+ code:
+ description: A required code to toggle the alarm control panel chime with.
+ example: 1234
diff --git a/homeassistant/components/cover/services.yaml b/homeassistant/components/cover/services.yaml
index 1a3e020ed87a13..79f00180a8946d 100644
--- a/homeassistant/components/cover/services.yaml
+++ b/homeassistant/components/cover/services.yaml
@@ -1,63 +1,63 @@
-# Describes the format for available cover services
-
-open_cover:
- description: Open all or specified cover.
- fields:
- entity_id:
- description: Name(s) of cover(s) to open.
- example: 'cover.living_room'
-
-close_cover:
- description: Close all or specified cover.
- fields:
- entity_id:
- description: Name(s) of cover(s) to close.
- example: 'cover.living_room'
-
-set_cover_position:
- description: Move to specific position all or specified cover.
- fields:
- entity_id:
- description: Name(s) of cover(s) to set cover position.
- example: 'cover.living_room'
- position:
- description: Position of the cover (0 to 100).
- example: 30
-
-stop_cover:
- description: Stop all or specified cover.
- fields:
- entity_id:
- description: Name(s) of cover(s) to stop.
- example: 'cover.living_room'
-
-open_cover_tilt:
- description: Open all or specified cover tilt.
- fields:
- entity_id:
- description: Name(s) of cover(s) tilt to open.
- example: 'cover.living_room'
-
-close_cover_tilt:
- description: Close all or specified cover tilt.
- fields:
- entity_id:
- description: Name(s) of cover(s) to close tilt.
- example: 'cover.living_room'
-
-set_cover_tilt_position:
- description: Move to specific position all or specified cover tilt.
- fields:
- entity_id:
- description: Name(s) of cover(s) to set cover tilt position.
- example: 'cover.living_room'
- tilt_position:
- description: Tilt position of the cover (0 to 100).
- example: 30
-
-stop_cover_tilt:
- description: Stop all or specified cover.
- fields:
- entity_id:
- description: Name(s) of cover(s) to stop.
- example: 'cover.living_room'
+# Describes the format for available cover services
+
+open_cover:
+ description: Open all or specified cover.
+ fields:
+ entity_id:
+ description: Name(s) of cover(s) to open.
+ example: 'cover.living_room'
+
+close_cover:
+ description: Close all or specified cover.
+ fields:
+ entity_id:
+ description: Name(s) of cover(s) to close.
+ example: 'cover.living_room'
+
+set_cover_position:
+ description: Move to specific position all or specified cover.
+ fields:
+ entity_id:
+ description: Name(s) of cover(s) to set cover position.
+ example: 'cover.living_room'
+ position:
+ description: Position of the cover (0 to 100).
+ example: 30
+
+stop_cover:
+ description: Stop all or specified cover.
+ fields:
+ entity_id:
+ description: Name(s) of cover(s) to stop.
+ example: 'cover.living_room'
+
+open_cover_tilt:
+ description: Open all or specified cover tilt.
+ fields:
+ entity_id:
+ description: Name(s) of cover(s) tilt to open.
+ example: 'cover.living_room'
+
+close_cover_tilt:
+ description: Close all or specified cover tilt.
+ fields:
+ entity_id:
+ description: Name(s) of cover(s) to close tilt.
+ example: 'cover.living_room'
+
+set_cover_tilt_position:
+ description: Move to specific position all or specified cover tilt.
+ fields:
+ entity_id:
+ description: Name(s) of cover(s) to set cover tilt position.
+ example: 'cover.living_room'
+ tilt_position:
+ description: Tilt position of the cover (0 to 100).
+ example: 30
+
+stop_cover_tilt:
+ description: Stop all or specified cover.
+ fields:
+ entity_id:
+ description: Name(s) of cover(s) to stop.
+ example: 'cover.living_room'
diff --git a/tests/components/light/test_mqtt_json.py b/tests/components/light/test_mqtt_json.py
index d7eb80980ca365..ba306a81a34eda 100644
--- a/tests/components/light/test_mqtt_json.py
+++ b/tests/components/light/test_mqtt_json.py
@@ -1,597 +1,597 @@
-"""The tests for the MQTT JSON light platform.
-
-Configuration with RGB, brightness, color temp, effect, white value and XY:
-
-light:
- platform: mqtt_json
- name: mqtt_json_light_1
- state_topic: "home/rgb1"
- command_topic: "home/rgb1/set"
- brightness: true
- color_temp: true
- effect: true
- rgb: true
- white_value: true
- xy: true
-
-Configuration with RGB, brightness, color temp, effect, white value:
-
-light:
- platform: mqtt_json
- name: mqtt_json_light_1
- state_topic: "home/rgb1"
- command_topic: "home/rgb1/set"
- brightness: true
- color_temp: true
- effect: true
- rgb: true
- white_value: true
-
-Configuration with RGB, brightness, color temp and effect:
-
-light:
- platform: mqtt_json
- name: mqtt_json_light_1
- state_topic: "home/rgb1"
- command_topic: "home/rgb1/set"
- brightness: true
- color_temp: true
- effect: true
- rgb: true
-
-Configuration with RGB, brightness and color temp:
-
-light:
- platform: mqtt_json
- name: mqtt_json_light_1
- state_topic: "home/rgb1"
- command_topic: "home/rgb1/set"
- brightness: true
- rgb: true
- color_temp: true
-
-Configuration with RGB, brightness:
-
-light:
- platform: mqtt_json
- name: mqtt_json_light_1
- state_topic: "home/rgb1"
- command_topic: "home/rgb1/set"
- brightness: true
- rgb: true
-
-Config without RGB:
-
-light:
- platform: mqtt_json
- name: mqtt_json_light_1
- state_topic: "home/rgb1"
- command_topic: "home/rgb1/set"
- brightness: true
-
-Config without RGB and brightness:
-
-light:
- platform: mqtt_json
- name: mqtt_json_light_1
- state_topic: "home/rgb1"
- command_topic: "home/rgb1/set"
-
-Config with brightness and scale:
-
-light:
- platform: mqtt_json
- name: test
- state_topic: "mqtt_json_light_1"
- command_topic: "mqtt_json_light_1/set"
- brightness: true
- brightness_scale: 99
-"""
-
-import json
-import unittest
-
-from homeassistant.setup import setup_component
-from homeassistant.const import (
- STATE_ON, STATE_OFF, STATE_UNAVAILABLE, ATTR_ASSUMED_STATE,
- ATTR_SUPPORTED_FEATURES)
-import homeassistant.components.light as light
-from tests.common import (
- get_test_home_assistant, mock_mqtt_component, fire_mqtt_message,
- assert_setup_component)
-
-
-class TestLightMQTTJSON(unittest.TestCase):
- """Test the MQTT JSON light."""
-
- def setUp(self): # pylint: disable=invalid-name
- """Setup things to be run when tests are started."""
- self.hass = get_test_home_assistant()
- self.mock_publish = mock_mqtt_component(self.hass)
-
- def tearDown(self): # pylint: disable=invalid-name
- """Stop everything that was started."""
- self.hass.stop()
-
- def test_fail_setup_if_no_command_topic(self): \
- # pylint: disable=invalid-name
- """Test if setup fails with no command topic."""
- with assert_setup_component(0, light.DOMAIN):
- assert setup_component(self.hass, light.DOMAIN, {
- light.DOMAIN: {
- 'platform': 'mqtt_json',
- 'name': 'test',
- }
- })
- self.assertIsNone(self.hass.states.get('light.test'))
-
- def test_no_color_brightness_color_temp_white_val_if_no_topics(self): \
- # pylint: disable=invalid-name
- """Test for no RGB, brightness, color temp, effect, white val or XY."""
- assert setup_component(self.hass, light.DOMAIN, {
- light.DOMAIN: {
- 'platform': 'mqtt_json',
- 'name': 'test',
- 'state_topic': 'test_light_rgb',
- 'command_topic': 'test_light_rgb/set',
- }
- })
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_OFF, state.state)
- self.assertEqual(40, state.attributes.get(ATTR_SUPPORTED_FEATURES))
- self.assertIsNone(state.attributes.get('rgb_color'))
- self.assertIsNone(state.attributes.get('brightness'))
- self.assertIsNone(state.attributes.get('color_temp'))
- self.assertIsNone(state.attributes.get('effect'))
- self.assertIsNone(state.attributes.get('white_value'))
- self.assertIsNone(state.attributes.get('xy_color'))
-
- fire_mqtt_message(self.hass, 'test_light_rgb', '{"state":"ON"}')
- self.hass.block_till_done()
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_ON, state.state)
- self.assertIsNone(state.attributes.get('rgb_color'))
- self.assertIsNone(state.attributes.get('brightness'))
- self.assertIsNone(state.attributes.get('color_temp'))
- self.assertIsNone(state.attributes.get('effect'))
- self.assertIsNone(state.attributes.get('white_value'))
- self.assertIsNone(state.attributes.get('xy_color'))
-
- def test_controlling_state_via_topic(self): \
- # pylint: disable=invalid-name
- """Test the controlling of the state via topic."""
- assert setup_component(self.hass, light.DOMAIN, {
- light.DOMAIN: {
- 'platform': 'mqtt_json',
- 'name': 'test',
- 'state_topic': 'test_light_rgb',
- 'command_topic': 'test_light_rgb/set',
- 'brightness': True,
- 'color_temp': True,
- 'effect': True,
- 'rgb': True,
- 'white_value': True,
- 'xy': True,
- 'qos': '0'
- }
- })
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_OFF, state.state)
- self.assertEqual(255, state.attributes.get(ATTR_SUPPORTED_FEATURES))
- self.assertIsNone(state.attributes.get('rgb_color'))
- self.assertIsNone(state.attributes.get('brightness'))
- self.assertIsNone(state.attributes.get('color_temp'))
- self.assertIsNone(state.attributes.get('effect'))
- self.assertIsNone(state.attributes.get('white_value'))
- self.assertIsNone(state.attributes.get('xy_color'))
- self.assertFalse(state.attributes.get(ATTR_ASSUMED_STATE))
-
- # Turn on the light, full white
- fire_mqtt_message(self.hass, 'test_light_rgb',
- '{"state":"ON",'
- '"color":{"r":255,"g":255,"b":255,'
- '"x":0.123,"y":0.123},'
- '"brightness":255,'
- '"color_temp":155,'
- '"effect":"colorloop",'
- '"white_value":150}')
- self.hass.block_till_done()
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_ON, state.state)
- self.assertEqual([255, 255, 255], state.attributes.get('rgb_color'))
- self.assertEqual(255, state.attributes.get('brightness'))
- self.assertEqual(155, state.attributes.get('color_temp'))
- self.assertEqual('colorloop', state.attributes.get('effect'))
- self.assertEqual(150, state.attributes.get('white_value'))
- self.assertEqual([0.123, 0.123], state.attributes.get('xy_color'))
-
- # Turn the light off
- fire_mqtt_message(self.hass, 'test_light_rgb', '{"state":"OFF"}')
- self.hass.block_till_done()
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_OFF, state.state)
-
- fire_mqtt_message(self.hass, 'test_light_rgb',
- '{"state":"ON",'
- '"brightness":100}')
- self.hass.block_till_done()
-
- light_state = self.hass.states.get('light.test')
- self.hass.block_till_done()
- self.assertEqual(100,
- light_state.attributes['brightness'])
-
- fire_mqtt_message(self.hass, 'test_light_rgb',
- '{"state":"ON",'
- '"color":{"r":125,"g":125,"b":125}}')
- self.hass.block_till_done()
-
- light_state = self.hass.states.get('light.test')
- self.assertEqual([125, 125, 125],
- light_state.attributes.get('rgb_color'))
-
- fire_mqtt_message(self.hass, 'test_light_rgb',
- '{"state":"ON",'
- '"color":{"x":0.135,"y":0.135}}')
- self.hass.block_till_done()
-
- light_state = self.hass.states.get('light.test')
- self.assertEqual([0.135, 0.135],
- light_state.attributes.get('xy_color'))
-
- fire_mqtt_message(self.hass, 'test_light_rgb',
- '{"state":"ON",'
- '"color_temp":155}')
- self.hass.block_till_done()
-
- light_state = self.hass.states.get('light.test')
- self.assertEqual(155, light_state.attributes.get('color_temp'))
-
- fire_mqtt_message(self.hass, 'test_light_rgb',
- '{"state":"ON",'
- '"effect":"colorloop"}')
- self.hass.block_till_done()
-
- light_state = self.hass.states.get('light.test')
- self.assertEqual('colorloop', light_state.attributes.get('effect'))
-
- fire_mqtt_message(self.hass, 'test_light_rgb',
- '{"state":"ON",'
- '"white_value":155}')
- self.hass.block_till_done()
-
- light_state = self.hass.states.get('light.test')
- self.assertEqual(155, light_state.attributes.get('white_value'))
-
- def test_sending_mqtt_commands_and_optimistic(self): \
- # pylint: disable=invalid-name
- """Test the sending of command in optimistic mode."""
- assert setup_component(self.hass, light.DOMAIN, {
- light.DOMAIN: {
- 'platform': 'mqtt_json',
- 'name': 'test',
- 'command_topic': 'test_light_rgb/set',
- 'brightness': True,
- 'color_temp': True,
- 'effect': True,
- 'rgb': True,
- 'white_value': True,
- 'qos': 2
- }
- })
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_OFF, state.state)
- self.assertEqual(191, state.attributes.get(ATTR_SUPPORTED_FEATURES))
- self.assertTrue(state.attributes.get(ATTR_ASSUMED_STATE))
-
- light.turn_on(self.hass, 'light.test')
- self.hass.block_till_done()
-
- self.mock_publish.async_publish.assert_called_once_with(
- 'test_light_rgb/set', '{"state": "ON"}', 2, False)
- self.mock_publish.async_publish.reset_mock()
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_ON, state.state)
-
- light.turn_off(self.hass, 'light.test')
- self.hass.block_till_done()
-
- self.mock_publish.async_publish.assert_called_once_with(
- 'test_light_rgb/set', '{"state": "OFF"}', 2, False)
- self.mock_publish.async_publish.reset_mock()
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_OFF, state.state)
-
- light.turn_on(self.hass, 'light.test',
- brightness=50, color_temp=155, effect='colorloop',
- white_value=170)
- self.hass.block_till_done()
-
- self.assertEqual('test_light_rgb/set',
- self.mock_publish.async_publish.mock_calls[0][1][0])
- self.assertEqual(2,
- self.mock_publish.async_publish.mock_calls[0][1][2])
- self.assertEqual(False,
- self.mock_publish.async_publish.mock_calls[0][1][3])
- # Get the sent message
- message_json = json.loads(
- self.mock_publish.async_publish.mock_calls[0][1][1])
- self.assertEqual(50, message_json["brightness"])
- self.assertEqual(155, message_json["color_temp"])
- self.assertEqual('colorloop', message_json["effect"])
- self.assertEqual(170, message_json["white_value"])
- self.assertEqual("ON", message_json["state"])
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_ON, state.state)
- self.assertEqual(50, state.attributes['brightness'])
- self.assertEqual(155, state.attributes['color_temp'])
- self.assertEqual('colorloop', state.attributes['effect'])
- self.assertEqual(170, state.attributes['white_value'])
-
- def test_flash_short_and_long(self): \
- # pylint: disable=invalid-name
- """Test for flash length being sent when included."""
- assert setup_component(self.hass, light.DOMAIN, {
- light.DOMAIN: {
- 'platform': 'mqtt_json',
- 'name': 'test',
- 'state_topic': 'test_light_rgb',
- 'command_topic': 'test_light_rgb/set',
- 'flash_time_short': 5,
- 'flash_time_long': 15,
- 'qos': 0
- }
- })
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_OFF, state.state)
- self.assertEqual(40, state.attributes.get(ATTR_SUPPORTED_FEATURES))
-
- light.turn_on(self.hass, 'light.test', flash="short")
- self.hass.block_till_done()
-
- self.assertEqual('test_light_rgb/set',
- self.mock_publish.async_publish.mock_calls[0][1][0])
- self.assertEqual(0,
- self.mock_publish.async_publish.mock_calls[0][1][2])
- self.assertEqual(False,
- self.mock_publish.async_publish.mock_calls[0][1][3])
- # Get the sent message
- message_json = json.loads(
- self.mock_publish.async_publish.mock_calls[0][1][1])
- self.assertEqual(5, message_json["flash"])
- self.assertEqual("ON", message_json["state"])
-
- self.mock_publish.async_publish.reset_mock()
- light.turn_on(self.hass, 'light.test', flash="long")
- self.hass.block_till_done()
-
- self.assertEqual('test_light_rgb/set',
- self.mock_publish.async_publish.mock_calls[0][1][0])
- self.assertEqual(0,
- self.mock_publish.async_publish.mock_calls[0][1][2])
- self.assertEqual(False,
- self.mock_publish.async_publish.mock_calls[0][1][3])
- # Get the sent message
- message_json = json.loads(
- self.mock_publish.async_publish.mock_calls[0][1][1])
- self.assertEqual(15, message_json["flash"])
- self.assertEqual("ON", message_json["state"])
-
- def test_transition(self):
- """Test for transition time being sent when included."""
- assert setup_component(self.hass, light.DOMAIN, {
- light.DOMAIN: {
- 'platform': 'mqtt_json',
- 'name': 'test',
- 'state_topic': 'test_light_rgb',
- 'command_topic': 'test_light_rgb/set',
- 'qos': 0
- }
- })
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_OFF, state.state)
- self.assertEqual(40, state.attributes.get(ATTR_SUPPORTED_FEATURES))
-
- light.turn_on(self.hass, 'light.test', transition=10)
- self.hass.block_till_done()
-
- self.assertEqual('test_light_rgb/set',
- self.mock_publish.async_publish.mock_calls[0][1][0])
- self.assertEqual(0,
- self.mock_publish.async_publish.mock_calls[0][1][2])
- self.assertEqual(False,
- self.mock_publish.async_publish.mock_calls[0][1][3])
- # Get the sent message
- message_json = json.loads(
- self.mock_publish.async_publish.mock_calls[0][1][1])
- self.assertEqual(10, message_json["transition"])
- self.assertEqual("ON", message_json["state"])
-
- # Transition back off
- light.turn_off(self.hass, 'light.test', transition=10)
- self.hass.block_till_done()
-
- self.assertEqual('test_light_rgb/set',
- self.mock_publish.async_publish.mock_calls[1][1][0])
- self.assertEqual(0,
- self.mock_publish.async_publish.mock_calls[1][1][2])
- self.assertEqual(False,
- self.mock_publish.async_publish.mock_calls[1][1][3])
- # Get the sent message
- message_json = json.loads(
- self.mock_publish.async_publish.mock_calls[1][1][1])
- self.assertEqual(10, message_json["transition"])
- self.assertEqual("OFF", message_json["state"])
-
- def test_brightness_scale(self):
- """Test for brightness scaling."""
- assert setup_component(self.hass, light.DOMAIN, {
- light.DOMAIN: {
- 'platform': 'mqtt_json',
- 'name': 'test',
- 'state_topic': 'test_light_bright_scale',
- 'command_topic': 'test_light_bright_scale/set',
- 'brightness': True,
- 'brightness_scale': 99
- }
- })
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_OFF, state.state)
- self.assertIsNone(state.attributes.get('brightness'))
- self.assertFalse(state.attributes.get(ATTR_ASSUMED_STATE))
-
- # Turn on the light
- fire_mqtt_message(self.hass, 'test_light_bright_scale',
- '{"state":"ON"}')
- self.hass.block_till_done()
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_ON, state.state)
- self.assertEqual(255, state.attributes.get('brightness'))
-
- # Turn on the light with brightness
- fire_mqtt_message(self.hass, 'test_light_bright_scale',
- '{"state":"ON",'
- '"brightness": 99}')
- self.hass.block_till_done()
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_ON, state.state)
- self.assertEqual(255, state.attributes.get('brightness'))
-
- def test_invalid_color_brightness_and_white_values(self): \
- # pylint: disable=invalid-name
- """Test that invalid color/brightness/white values are ignored."""
- assert setup_component(self.hass, light.DOMAIN, {
- light.DOMAIN: {
- 'platform': 'mqtt_json',
- 'name': 'test',
- 'state_topic': 'test_light_rgb',
- 'command_topic': 'test_light_rgb/set',
- 'brightness': True,
- 'rgb': True,
- 'white_value': True,
- 'qos': '0'
- }
- })
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_OFF, state.state)
- self.assertEqual(185, state.attributes.get(ATTR_SUPPORTED_FEATURES))
- self.assertIsNone(state.attributes.get('rgb_color'))
- self.assertIsNone(state.attributes.get('brightness'))
- self.assertIsNone(state.attributes.get('white_value'))
- self.assertFalse(state.attributes.get(ATTR_ASSUMED_STATE))
-
- # Turn on the light
- fire_mqtt_message(self.hass, 'test_light_rgb',
- '{"state":"ON",'
- '"color":{"r":255,"g":255,"b":255},'
- '"brightness": 255,'
- '"white_value": 255}')
- self.hass.block_till_done()
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_ON, state.state)
- self.assertEqual([255, 255, 255], state.attributes.get('rgb_color'))
- self.assertEqual(255, state.attributes.get('brightness'))
- self.assertEqual(255, state.attributes.get('white_value'))
-
- # Bad color values
- fire_mqtt_message(self.hass, 'test_light_rgb',
- '{"state":"ON",'
- '"color":{"r":"bad","g":"val","b":"test"}}')
- self.hass.block_till_done()
-
- # Color should not have changed
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_ON, state.state)
- self.assertEqual([255, 255, 255], state.attributes.get('rgb_color'))
-
- # Bad brightness values
- fire_mqtt_message(self.hass, 'test_light_rgb',
- '{"state":"ON",'
- '"brightness": "badValue"}')
- self.hass.block_till_done()
-
- # Brightness should not have changed
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_ON, state.state)
- self.assertEqual(255, state.attributes.get('brightness'))
-
- # Bad white value
- fire_mqtt_message(self.hass, 'test_light_rgb',
- '{"state":"ON",'
- '"white_value": "badValue"}')
- self.hass.block_till_done()
-
- # White value should not have changed
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_ON, state.state)
- self.assertEqual(255, state.attributes.get('white_value'))
-
- def test_default_availability_payload(self):
- """Test availability by default payload with defined topic."""
- self.assertTrue(setup_component(self.hass, light.DOMAIN, {
- light.DOMAIN: {
- 'platform': 'mqtt_json',
- 'name': 'test',
- 'state_topic': 'test_light_rgb',
- 'command_topic': 'test_light_rgb/set',
- 'availability_topic': 'availability-topic'
- }
- }))
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_UNAVAILABLE, state.state)
-
- fire_mqtt_message(self.hass, 'availability-topic', 'online')
- self.hass.block_till_done()
-
- state = self.hass.states.get('light.test')
- self.assertNotEqual(STATE_UNAVAILABLE, state.state)
-
- fire_mqtt_message(self.hass, 'availability-topic', 'offline')
- self.hass.block_till_done()
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_UNAVAILABLE, state.state)
-
- def test_custom_availability_payload(self):
- """Test availability by custom payload with defined topic."""
- self.assertTrue(setup_component(self.hass, light.DOMAIN, {
- light.DOMAIN: {
- 'platform': 'mqtt_json',
- 'name': 'test',
- 'state_topic': 'test_light_rgb',
- 'command_topic': 'test_light_rgb/set',
- 'availability_topic': 'availability-topic',
- 'payload_available': 'good',
- 'payload_not_available': 'nogood'
- }
- }))
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_UNAVAILABLE, state.state)
-
- fire_mqtt_message(self.hass, 'availability-topic', 'good')
- self.hass.block_till_done()
-
- state = self.hass.states.get('light.test')
- self.assertNotEqual(STATE_UNAVAILABLE, state.state)
-
- fire_mqtt_message(self.hass, 'availability-topic', 'nogood')
- self.hass.block_till_done()
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_UNAVAILABLE, state.state)
+"""The tests for the MQTT JSON light platform.
+
+Configuration with RGB, brightness, color temp, effect, white value and XY:
+
+light:
+ platform: mqtt_json
+ name: mqtt_json_light_1
+ state_topic: "home/rgb1"
+ command_topic: "home/rgb1/set"
+ brightness: true
+ color_temp: true
+ effect: true
+ rgb: true
+ white_value: true
+ xy: true
+
+Configuration with RGB, brightness, color temp, effect, white value:
+
+light:
+ platform: mqtt_json
+ name: mqtt_json_light_1
+ state_topic: "home/rgb1"
+ command_topic: "home/rgb1/set"
+ brightness: true
+ color_temp: true
+ effect: true
+ rgb: true
+ white_value: true
+
+Configuration with RGB, brightness, color temp and effect:
+
+light:
+ platform: mqtt_json
+ name: mqtt_json_light_1
+ state_topic: "home/rgb1"
+ command_topic: "home/rgb1/set"
+ brightness: true
+ color_temp: true
+ effect: true
+ rgb: true
+
+Configuration with RGB, brightness and color temp:
+
+light:
+ platform: mqtt_json
+ name: mqtt_json_light_1
+ state_topic: "home/rgb1"
+ command_topic: "home/rgb1/set"
+ brightness: true
+ rgb: true
+ color_temp: true
+
+Configuration with RGB, brightness:
+
+light:
+ platform: mqtt_json
+ name: mqtt_json_light_1
+ state_topic: "home/rgb1"
+ command_topic: "home/rgb1/set"
+ brightness: true
+ rgb: true
+
+Config without RGB:
+
+light:
+ platform: mqtt_json
+ name: mqtt_json_light_1
+ state_topic: "home/rgb1"
+ command_topic: "home/rgb1/set"
+ brightness: true
+
+Config without RGB and brightness:
+
+light:
+ platform: mqtt_json
+ name: mqtt_json_light_1
+ state_topic: "home/rgb1"
+ command_topic: "home/rgb1/set"
+
+Config with brightness and scale:
+
+light:
+ platform: mqtt_json
+ name: test
+ state_topic: "mqtt_json_light_1"
+ command_topic: "mqtt_json_light_1/set"
+ brightness: true
+ brightness_scale: 99
+"""
+
+import json
+import unittest
+
+from homeassistant.setup import setup_component
+from homeassistant.const import (
+ STATE_ON, STATE_OFF, STATE_UNAVAILABLE, ATTR_ASSUMED_STATE,
+ ATTR_SUPPORTED_FEATURES)
+import homeassistant.components.light as light
+from tests.common import (
+ get_test_home_assistant, mock_mqtt_component, fire_mqtt_message,
+ assert_setup_component)
+
+
+class TestLightMQTTJSON(unittest.TestCase):
+ """Test the MQTT JSON light."""
+
+ def setUp(self): # pylint: disable=invalid-name
+ """Setup things to be run when tests are started."""
+ self.hass = get_test_home_assistant()
+ self.mock_publish = mock_mqtt_component(self.hass)
+
+ def tearDown(self): # pylint: disable=invalid-name
+ """Stop everything that was started."""
+ self.hass.stop()
+
+ def test_fail_setup_if_no_command_topic(self): \
+ # pylint: disable=invalid-name
+ """Test if setup fails with no command topic."""
+ with assert_setup_component(0, light.DOMAIN):
+ assert setup_component(self.hass, light.DOMAIN, {
+ light.DOMAIN: {
+ 'platform': 'mqtt_json',
+ 'name': 'test',
+ }
+ })
+ self.assertIsNone(self.hass.states.get('light.test'))
+
+ def test_no_color_brightness_color_temp_white_val_if_no_topics(self): \
+ # pylint: disable=invalid-name
+ """Test for no RGB, brightness, color temp, effect, white val or XY."""
+ assert setup_component(self.hass, light.DOMAIN, {
+ light.DOMAIN: {
+ 'platform': 'mqtt_json',
+ 'name': 'test',
+ 'state_topic': 'test_light_rgb',
+ 'command_topic': 'test_light_rgb/set',
+ }
+ })
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_OFF, state.state)
+ self.assertEqual(40, state.attributes.get(ATTR_SUPPORTED_FEATURES))
+ self.assertIsNone(state.attributes.get('rgb_color'))
+ self.assertIsNone(state.attributes.get('brightness'))
+ self.assertIsNone(state.attributes.get('color_temp'))
+ self.assertIsNone(state.attributes.get('effect'))
+ self.assertIsNone(state.attributes.get('white_value'))
+ self.assertIsNone(state.attributes.get('xy_color'))
+
+ fire_mqtt_message(self.hass, 'test_light_rgb', '{"state":"ON"}')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_ON, state.state)
+ self.assertIsNone(state.attributes.get('rgb_color'))
+ self.assertIsNone(state.attributes.get('brightness'))
+ self.assertIsNone(state.attributes.get('color_temp'))
+ self.assertIsNone(state.attributes.get('effect'))
+ self.assertIsNone(state.attributes.get('white_value'))
+ self.assertIsNone(state.attributes.get('xy_color'))
+
+ def test_controlling_state_via_topic(self): \
+ # pylint: disable=invalid-name
+ """Test the controlling of the state via topic."""
+ assert setup_component(self.hass, light.DOMAIN, {
+ light.DOMAIN: {
+ 'platform': 'mqtt_json',
+ 'name': 'test',
+ 'state_topic': 'test_light_rgb',
+ 'command_topic': 'test_light_rgb/set',
+ 'brightness': True,
+ 'color_temp': True,
+ 'effect': True,
+ 'rgb': True,
+ 'white_value': True,
+ 'xy': True,
+ 'qos': '0'
+ }
+ })
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_OFF, state.state)
+ self.assertEqual(255, state.attributes.get(ATTR_SUPPORTED_FEATURES))
+ self.assertIsNone(state.attributes.get('rgb_color'))
+ self.assertIsNone(state.attributes.get('brightness'))
+ self.assertIsNone(state.attributes.get('color_temp'))
+ self.assertIsNone(state.attributes.get('effect'))
+ self.assertIsNone(state.attributes.get('white_value'))
+ self.assertIsNone(state.attributes.get('xy_color'))
+ self.assertFalse(state.attributes.get(ATTR_ASSUMED_STATE))
+
+ # Turn on the light, full white
+ fire_mqtt_message(self.hass, 'test_light_rgb',
+ '{"state":"ON",'
+ '"color":{"r":255,"g":255,"b":255,'
+ '"x":0.123,"y":0.123},'
+ '"brightness":255,'
+ '"color_temp":155,'
+ '"effect":"colorloop",'
+ '"white_value":150}')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_ON, state.state)
+ self.assertEqual([255, 255, 255], state.attributes.get('rgb_color'))
+ self.assertEqual(255, state.attributes.get('brightness'))
+ self.assertEqual(155, state.attributes.get('color_temp'))
+ self.assertEqual('colorloop', state.attributes.get('effect'))
+ self.assertEqual(150, state.attributes.get('white_value'))
+ self.assertEqual([0.123, 0.123], state.attributes.get('xy_color'))
+
+ # Turn the light off
+ fire_mqtt_message(self.hass, 'test_light_rgb', '{"state":"OFF"}')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_OFF, state.state)
+
+ fire_mqtt_message(self.hass, 'test_light_rgb',
+ '{"state":"ON",'
+ '"brightness":100}')
+ self.hass.block_till_done()
+
+ light_state = self.hass.states.get('light.test')
+ self.hass.block_till_done()
+ self.assertEqual(100,
+ light_state.attributes['brightness'])
+
+ fire_mqtt_message(self.hass, 'test_light_rgb',
+ '{"state":"ON",'
+ '"color":{"r":125,"g":125,"b":125}}')
+ self.hass.block_till_done()
+
+ light_state = self.hass.states.get('light.test')
+ self.assertEqual([125, 125, 125],
+ light_state.attributes.get('rgb_color'))
+
+ fire_mqtt_message(self.hass, 'test_light_rgb',
+ '{"state":"ON",'
+ '"color":{"x":0.135,"y":0.135}}')
+ self.hass.block_till_done()
+
+ light_state = self.hass.states.get('light.test')
+ self.assertEqual([0.135, 0.135],
+ light_state.attributes.get('xy_color'))
+
+ fire_mqtt_message(self.hass, 'test_light_rgb',
+ '{"state":"ON",'
+ '"color_temp":155}')
+ self.hass.block_till_done()
+
+ light_state = self.hass.states.get('light.test')
+ self.assertEqual(155, light_state.attributes.get('color_temp'))
+
+ fire_mqtt_message(self.hass, 'test_light_rgb',
+ '{"state":"ON",'
+ '"effect":"colorloop"}')
+ self.hass.block_till_done()
+
+ light_state = self.hass.states.get('light.test')
+ self.assertEqual('colorloop', light_state.attributes.get('effect'))
+
+ fire_mqtt_message(self.hass, 'test_light_rgb',
+ '{"state":"ON",'
+ '"white_value":155}')
+ self.hass.block_till_done()
+
+ light_state = self.hass.states.get('light.test')
+ self.assertEqual(155, light_state.attributes.get('white_value'))
+
+ def test_sending_mqtt_commands_and_optimistic(self): \
+ # pylint: disable=invalid-name
+ """Test the sending of command in optimistic mode."""
+ assert setup_component(self.hass, light.DOMAIN, {
+ light.DOMAIN: {
+ 'platform': 'mqtt_json',
+ 'name': 'test',
+ 'command_topic': 'test_light_rgb/set',
+ 'brightness': True,
+ 'color_temp': True,
+ 'effect': True,
+ 'rgb': True,
+ 'white_value': True,
+ 'qos': 2
+ }
+ })
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_OFF, state.state)
+ self.assertEqual(191, state.attributes.get(ATTR_SUPPORTED_FEATURES))
+ self.assertTrue(state.attributes.get(ATTR_ASSUMED_STATE))
+
+ light.turn_on(self.hass, 'light.test')
+ self.hass.block_till_done()
+
+ self.mock_publish.async_publish.assert_called_once_with(
+ 'test_light_rgb/set', '{"state": "ON"}', 2, False)
+ self.mock_publish.async_publish.reset_mock()
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_ON, state.state)
+
+ light.turn_off(self.hass, 'light.test')
+ self.hass.block_till_done()
+
+ self.mock_publish.async_publish.assert_called_once_with(
+ 'test_light_rgb/set', '{"state": "OFF"}', 2, False)
+ self.mock_publish.async_publish.reset_mock()
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_OFF, state.state)
+
+ light.turn_on(self.hass, 'light.test',
+ brightness=50, color_temp=155, effect='colorloop',
+ white_value=170)
+ self.hass.block_till_done()
+
+ self.assertEqual('test_light_rgb/set',
+ self.mock_publish.async_publish.mock_calls[0][1][0])
+ self.assertEqual(2,
+ self.mock_publish.async_publish.mock_calls[0][1][2])
+ self.assertEqual(False,
+ self.mock_publish.async_publish.mock_calls[0][1][3])
+ # Get the sent message
+ message_json = json.loads(
+ self.mock_publish.async_publish.mock_calls[0][1][1])
+ self.assertEqual(50, message_json["brightness"])
+ self.assertEqual(155, message_json["color_temp"])
+ self.assertEqual('colorloop', message_json["effect"])
+ self.assertEqual(170, message_json["white_value"])
+ self.assertEqual("ON", message_json["state"])
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_ON, state.state)
+ self.assertEqual(50, state.attributes['brightness'])
+ self.assertEqual(155, state.attributes['color_temp'])
+ self.assertEqual('colorloop', state.attributes['effect'])
+ self.assertEqual(170, state.attributes['white_value'])
+
+ def test_flash_short_and_long(self): \
+ # pylint: disable=invalid-name
+ """Test for flash length being sent when included."""
+ assert setup_component(self.hass, light.DOMAIN, {
+ light.DOMAIN: {
+ 'platform': 'mqtt_json',
+ 'name': 'test',
+ 'state_topic': 'test_light_rgb',
+ 'command_topic': 'test_light_rgb/set',
+ 'flash_time_short': 5,
+ 'flash_time_long': 15,
+ 'qos': 0
+ }
+ })
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_OFF, state.state)
+ self.assertEqual(40, state.attributes.get(ATTR_SUPPORTED_FEATURES))
+
+ light.turn_on(self.hass, 'light.test', flash="short")
+ self.hass.block_till_done()
+
+ self.assertEqual('test_light_rgb/set',
+ self.mock_publish.async_publish.mock_calls[0][1][0])
+ self.assertEqual(0,
+ self.mock_publish.async_publish.mock_calls[0][1][2])
+ self.assertEqual(False,
+ self.mock_publish.async_publish.mock_calls[0][1][3])
+ # Get the sent message
+ message_json = json.loads(
+ self.mock_publish.async_publish.mock_calls[0][1][1])
+ self.assertEqual(5, message_json["flash"])
+ self.assertEqual("ON", message_json["state"])
+
+ self.mock_publish.async_publish.reset_mock()
+ light.turn_on(self.hass, 'light.test', flash="long")
+ self.hass.block_till_done()
+
+ self.assertEqual('test_light_rgb/set',
+ self.mock_publish.async_publish.mock_calls[0][1][0])
+ self.assertEqual(0,
+ self.mock_publish.async_publish.mock_calls[0][1][2])
+ self.assertEqual(False,
+ self.mock_publish.async_publish.mock_calls[0][1][3])
+ # Get the sent message
+ message_json = json.loads(
+ self.mock_publish.async_publish.mock_calls[0][1][1])
+ self.assertEqual(15, message_json["flash"])
+ self.assertEqual("ON", message_json["state"])
+
+ def test_transition(self):
+ """Test for transition time being sent when included."""
+ assert setup_component(self.hass, light.DOMAIN, {
+ light.DOMAIN: {
+ 'platform': 'mqtt_json',
+ 'name': 'test',
+ 'state_topic': 'test_light_rgb',
+ 'command_topic': 'test_light_rgb/set',
+ 'qos': 0
+ }
+ })
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_OFF, state.state)
+ self.assertEqual(40, state.attributes.get(ATTR_SUPPORTED_FEATURES))
+
+ light.turn_on(self.hass, 'light.test', transition=10)
+ self.hass.block_till_done()
+
+ self.assertEqual('test_light_rgb/set',
+ self.mock_publish.async_publish.mock_calls[0][1][0])
+ self.assertEqual(0,
+ self.mock_publish.async_publish.mock_calls[0][1][2])
+ self.assertEqual(False,
+ self.mock_publish.async_publish.mock_calls[0][1][3])
+ # Get the sent message
+ message_json = json.loads(
+ self.mock_publish.async_publish.mock_calls[0][1][1])
+ self.assertEqual(10, message_json["transition"])
+ self.assertEqual("ON", message_json["state"])
+
+ # Transition back off
+ light.turn_off(self.hass, 'light.test', transition=10)
+ self.hass.block_till_done()
+
+ self.assertEqual('test_light_rgb/set',
+ self.mock_publish.async_publish.mock_calls[1][1][0])
+ self.assertEqual(0,
+ self.mock_publish.async_publish.mock_calls[1][1][2])
+ self.assertEqual(False,
+ self.mock_publish.async_publish.mock_calls[1][1][3])
+ # Get the sent message
+ message_json = json.loads(
+ self.mock_publish.async_publish.mock_calls[1][1][1])
+ self.assertEqual(10, message_json["transition"])
+ self.assertEqual("OFF", message_json["state"])
+
+ def test_brightness_scale(self):
+ """Test for brightness scaling."""
+ assert setup_component(self.hass, light.DOMAIN, {
+ light.DOMAIN: {
+ 'platform': 'mqtt_json',
+ 'name': 'test',
+ 'state_topic': 'test_light_bright_scale',
+ 'command_topic': 'test_light_bright_scale/set',
+ 'brightness': True,
+ 'brightness_scale': 99
+ }
+ })
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_OFF, state.state)
+ self.assertIsNone(state.attributes.get('brightness'))
+ self.assertFalse(state.attributes.get(ATTR_ASSUMED_STATE))
+
+ # Turn on the light
+ fire_mqtt_message(self.hass, 'test_light_bright_scale',
+ '{"state":"ON"}')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_ON, state.state)
+ self.assertEqual(255, state.attributes.get('brightness'))
+
+ # Turn on the light with brightness
+ fire_mqtt_message(self.hass, 'test_light_bright_scale',
+ '{"state":"ON",'
+ '"brightness": 99}')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_ON, state.state)
+ self.assertEqual(255, state.attributes.get('brightness'))
+
+ def test_invalid_color_brightness_and_white_values(self): \
+ # pylint: disable=invalid-name
+ """Test that invalid color/brightness/white values are ignored."""
+ assert setup_component(self.hass, light.DOMAIN, {
+ light.DOMAIN: {
+ 'platform': 'mqtt_json',
+ 'name': 'test',
+ 'state_topic': 'test_light_rgb',
+ 'command_topic': 'test_light_rgb/set',
+ 'brightness': True,
+ 'rgb': True,
+ 'white_value': True,
+ 'qos': '0'
+ }
+ })
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_OFF, state.state)
+ self.assertEqual(185, state.attributes.get(ATTR_SUPPORTED_FEATURES))
+ self.assertIsNone(state.attributes.get('rgb_color'))
+ self.assertIsNone(state.attributes.get('brightness'))
+ self.assertIsNone(state.attributes.get('white_value'))
+ self.assertFalse(state.attributes.get(ATTR_ASSUMED_STATE))
+
+ # Turn on the light
+ fire_mqtt_message(self.hass, 'test_light_rgb',
+ '{"state":"ON",'
+ '"color":{"r":255,"g":255,"b":255},'
+ '"brightness": 255,'
+ '"white_value": 255}')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_ON, state.state)
+ self.assertEqual([255, 255, 255], state.attributes.get('rgb_color'))
+ self.assertEqual(255, state.attributes.get('brightness'))
+ self.assertEqual(255, state.attributes.get('white_value'))
+
+ # Bad color values
+ fire_mqtt_message(self.hass, 'test_light_rgb',
+ '{"state":"ON",'
+ '"color":{"r":"bad","g":"val","b":"test"}}')
+ self.hass.block_till_done()
+
+ # Color should not have changed
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_ON, state.state)
+ self.assertEqual([255, 255, 255], state.attributes.get('rgb_color'))
+
+ # Bad brightness values
+ fire_mqtt_message(self.hass, 'test_light_rgb',
+ '{"state":"ON",'
+ '"brightness": "badValue"}')
+ self.hass.block_till_done()
+
+ # Brightness should not have changed
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_ON, state.state)
+ self.assertEqual(255, state.attributes.get('brightness'))
+
+ # Bad white value
+ fire_mqtt_message(self.hass, 'test_light_rgb',
+ '{"state":"ON",'
+ '"white_value": "badValue"}')
+ self.hass.block_till_done()
+
+ # White value should not have changed
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_ON, state.state)
+ self.assertEqual(255, state.attributes.get('white_value'))
+
+ def test_default_availability_payload(self):
+ """Test availability by default payload with defined topic."""
+ self.assertTrue(setup_component(self.hass, light.DOMAIN, {
+ light.DOMAIN: {
+ 'platform': 'mqtt_json',
+ 'name': 'test',
+ 'state_topic': 'test_light_rgb',
+ 'command_topic': 'test_light_rgb/set',
+ 'availability_topic': 'availability-topic'
+ }
+ }))
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_UNAVAILABLE, state.state)
+
+ fire_mqtt_message(self.hass, 'availability-topic', 'online')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('light.test')
+ self.assertNotEqual(STATE_UNAVAILABLE, state.state)
+
+ fire_mqtt_message(self.hass, 'availability-topic', 'offline')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_UNAVAILABLE, state.state)
+
+ def test_custom_availability_payload(self):
+ """Test availability by custom payload with defined topic."""
+ self.assertTrue(setup_component(self.hass, light.DOMAIN, {
+ light.DOMAIN: {
+ 'platform': 'mqtt_json',
+ 'name': 'test',
+ 'state_topic': 'test_light_rgb',
+ 'command_topic': 'test_light_rgb/set',
+ 'availability_topic': 'availability-topic',
+ 'payload_available': 'good',
+ 'payload_not_available': 'nogood'
+ }
+ }))
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_UNAVAILABLE, state.state)
+
+ fire_mqtt_message(self.hass, 'availability-topic', 'good')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('light.test')
+ self.assertNotEqual(STATE_UNAVAILABLE, state.state)
+
+ fire_mqtt_message(self.hass, 'availability-topic', 'nogood')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_UNAVAILABLE, state.state)
diff --git a/tests/components/light/test_mqtt_template.py b/tests/components/light/test_mqtt_template.py
index 62947c052270ef..5a01aa15fa2bf6 100644
--- a/tests/components/light/test_mqtt_template.py
+++ b/tests/components/light/test_mqtt_template.py
@@ -1,498 +1,498 @@
-"""The tests for the MQTT Template light platform.
-
-Configuration example with all features:
-
-light:
- platform: mqtt_template
- name: mqtt_template_light_1
- state_topic: 'home/rgb1'
- command_topic: 'home/rgb1/set'
- command_on_template: >
- on,{{ brightness|d }},{{ red|d }}-{{ green|d }}-{{ blue|d }}
- command_off_template: 'off'
- state_template: '{{ value.split(",")[0] }}'
- brightness_template: '{{ value.split(",")[1] }}'
- color_temp_template: '{{ value.split(",")[2] }}'
- white_value_template: '{{ value.split(",")[3] }}'
- red_template: '{{ value.split(",")[4].split("-")[0] }}'
- green_template: '{{ value.split(",")[4].split("-")[1] }}'
- blue_template: '{{ value.split(",")[4].split("-")[2] }}'
-
-If your light doesn't support brightness feature, omit `brightness_template`.
-
-If your light doesn't support color temp feature, omit `color_temp_template`.
-
-If your light doesn't support white value feature, omit `white_value_template`.
-
-If your light doesn't support RGB feature, omit `(red|green|blue)_template`.
-"""
-import unittest
-
-from homeassistant.setup import setup_component
-from homeassistant.const import (
- STATE_ON, STATE_OFF, STATE_UNAVAILABLE, ATTR_ASSUMED_STATE)
-import homeassistant.components.light as light
-from tests.common import (
- get_test_home_assistant, mock_mqtt_component, fire_mqtt_message,
- assert_setup_component)
-
-
-class TestLightMQTTTemplate(unittest.TestCase):
- """Test the MQTT Template light."""
-
- def setUp(self): # pylint: disable=invalid-name
- """Setup things to be run when tests are started."""
- self.hass = get_test_home_assistant()
- self.mock_publish = mock_mqtt_component(self.hass)
-
- def tearDown(self): # pylint: disable=invalid-name
- """Stop everything that was started."""
- self.hass.stop()
-
- def test_setup_fails(self): \
- # pylint: disable=invalid-name
- """Test that setup fails with missing required configuration items."""
- with assert_setup_component(0, light.DOMAIN):
- assert setup_component(self.hass, light.DOMAIN, {
- light.DOMAIN: {
- 'platform': 'mqtt_template',
- 'name': 'test',
- }
- })
- self.assertIsNone(self.hass.states.get('light.test'))
-
- def test_state_change_via_topic(self): \
- # pylint: disable=invalid-name
- """Test state change via topic."""
- with assert_setup_component(1, light.DOMAIN):
- assert setup_component(self.hass, light.DOMAIN, {
- light.DOMAIN: {
- 'platform': 'mqtt_template',
- 'name': 'test',
- 'state_topic': 'test_light_rgb',
- 'command_topic': 'test_light_rgb/set',
- 'command_on_template': 'on,'
- '{{ brightness|d }},'
- '{{ color_temp|d }},'
- '{{ white_value|d }},'
- '{{ red|d }}-'
- '{{ green|d }}-'
- '{{ blue|d }}',
- 'command_off_template': 'off',
- 'state_template': '{{ value.split(",")[0] }}'
- }
- })
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_OFF, state.state)
- self.assertIsNone(state.attributes.get('rgb_color'))
- self.assertIsNone(state.attributes.get('brightness'))
- self.assertIsNone(state.attributes.get('color_temp'))
- self.assertIsNone(state.attributes.get('white_value'))
- self.assertFalse(state.attributes.get(ATTR_ASSUMED_STATE))
-
- fire_mqtt_message(self.hass, 'test_light_rgb', 'on')
- self.hass.block_till_done()
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_ON, state.state)
- self.assertIsNone(state.attributes.get('rgb_color'))
- self.assertIsNone(state.attributes.get('brightness'))
- self.assertIsNone(state.attributes.get('color_temp'))
- self.assertIsNone(state.attributes.get('white_value'))
-
- def test_state_brightness_color_effect_temp_white_change_via_topic(self): \
- # pylint: disable=invalid-name
- """Test state, bri, color, effect, color temp, white val change."""
- with assert_setup_component(1, light.DOMAIN):
- assert setup_component(self.hass, light.DOMAIN, {
- light.DOMAIN: {
- 'platform': 'mqtt_template',
- 'name': 'test',
- 'effect_list': ['rainbow', 'colorloop'],
- 'state_topic': 'test_light_rgb',
- 'command_topic': 'test_light_rgb/set',
- 'command_on_template': 'on,'
- '{{ brightness|d }},'
- '{{ color_temp|d }},'
- '{{ white_value|d }},'
- '{{ red|d }}-'
- '{{ green|d }}-'
- '{{ blue|d }},'
- '{{ effect|d }}',
- 'command_off_template': 'off',
- 'state_template': '{{ value.split(",")[0] }}',
- 'brightness_template': '{{ value.split(",")[1] }}',
- 'color_temp_template': '{{ value.split(",")[2] }}',
- 'white_value_template': '{{ value.split(",")[3] }}',
- 'red_template': '{{ value.split(",")[4].'
- 'split("-")[0] }}',
- 'green_template': '{{ value.split(",")[4].'
- 'split("-")[1] }}',
- 'blue_template': '{{ value.split(",")[4].'
- 'split("-")[2] }}',
- 'effect_template': '{{ value.split(",")[5] }}'
- }
- })
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_OFF, state.state)
- self.assertIsNone(state.attributes.get('rgb_color'))
- self.assertIsNone(state.attributes.get('brightness'))
- self.assertIsNone(state.attributes.get('effect'))
- self.assertIsNone(state.attributes.get('color_temp'))
- self.assertIsNone(state.attributes.get('white_value'))
- self.assertFalse(state.attributes.get(ATTR_ASSUMED_STATE))
-
- # turn on the light, full white
- fire_mqtt_message(self.hass, 'test_light_rgb',
- 'on,255,145,123,255-128-64,')
- self.hass.block_till_done()
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_ON, state.state)
- self.assertEqual([255, 128, 64], state.attributes.get('rgb_color'))
- self.assertEqual(255, state.attributes.get('brightness'))
- self.assertEqual(145, state.attributes.get('color_temp'))
- self.assertEqual(123, state.attributes.get('white_value'))
- self.assertIsNone(state.attributes.get('effect'))
-
- # turn the light off
- fire_mqtt_message(self.hass, 'test_light_rgb', 'off')
- self.hass.block_till_done()
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_OFF, state.state)
-
- # lower the brightness
- fire_mqtt_message(self.hass, 'test_light_rgb', 'on,100')
- self.hass.block_till_done()
-
- light_state = self.hass.states.get('light.test')
- self.hass.block_till_done()
- self.assertEqual(100, light_state.attributes['brightness'])
-
- # change the color temp
- fire_mqtt_message(self.hass, 'test_light_rgb', 'on,,195')
- self.hass.block_till_done()
-
- light_state = self.hass.states.get('light.test')
- self.hass.block_till_done()
- self.assertEqual(195, light_state.attributes['color_temp'])
-
- # change the color
- fire_mqtt_message(self.hass, 'test_light_rgb', 'on,,,,41-42-43')
- self.hass.block_till_done()
-
- light_state = self.hass.states.get('light.test')
- self.assertEqual([41, 42, 43], light_state.attributes.get('rgb_color'))
-
- # change the white value
- fire_mqtt_message(self.hass, 'test_light_rgb', 'on,,,134')
- self.hass.block_till_done()
-
- light_state = self.hass.states.get('light.test')
- self.hass.block_till_done()
- self.assertEqual(134, light_state.attributes['white_value'])
-
- # change the effect
- fire_mqtt_message(self.hass, 'test_light_rgb',
- 'on,,,,41-42-43,rainbow')
- self.hass.block_till_done()
-
- light_state = self.hass.states.get('light.test')
- self.assertEqual('rainbow', light_state.attributes.get('effect'))
-
- def test_optimistic(self): \
- # pylint: disable=invalid-name
- """Test optimistic mode."""
- with assert_setup_component(1, light.DOMAIN):
- assert setup_component(self.hass, light.DOMAIN, {
- light.DOMAIN: {
- 'platform': 'mqtt_template',
- 'name': 'test',
- 'command_topic': 'test_light_rgb/set',
- 'command_on_template': 'on,'
- '{{ brightness|d }},'
- '{{ color_temp|d }},'
- '{{ white_value|d }},'
- '{{ red|d }}-'
- '{{ green|d }}-'
- '{{ blue|d }}',
- 'command_off_template': 'off',
- 'qos': 2
- }
- })
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_OFF, state.state)
- self.assertTrue(state.attributes.get(ATTR_ASSUMED_STATE))
-
- # turn on the light
- light.turn_on(self.hass, 'light.test')
- self.hass.block_till_done()
-
- self.mock_publish.async_publish.assert_called_once_with(
- 'test_light_rgb/set', 'on,,,,--', 2, False)
- self.mock_publish.async_publish.reset_mock()
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_ON, state.state)
-
- # turn the light off
- light.turn_off(self.hass, 'light.test')
- self.hass.block_till_done()
-
- self.mock_publish.async_publish.assert_called_once_with(
- 'test_light_rgb/set', 'off', 2, False)
- self.mock_publish.async_publish.reset_mock()
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_OFF, state.state)
-
- # turn on the light with brightness, color
- light.turn_on(self.hass, 'light.test', brightness=50,
- rgb_color=[75, 75, 75])
- self.hass.block_till_done()
-
- self.mock_publish.async_publish.assert_called_once_with(
- 'test_light_rgb/set', 'on,50,,,75-75-75', 2, False)
- self.mock_publish.async_publish.reset_mock()
-
- # turn on the light with color temp and white val
- light.turn_on(self.hass, 'light.test', color_temp=200, white_value=139)
- self.hass.block_till_done()
-
- self.mock_publish.async_publish.assert_called_once_with(
- 'test_light_rgb/set', 'on,,200,139,--', 2, False)
-
- # check the state
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_ON, state.state)
- self.assertEqual((75, 75, 75), state.attributes['rgb_color'])
- self.assertEqual(50, state.attributes['brightness'])
- self.assertEqual(200, state.attributes['color_temp'])
- self.assertEqual(139, state.attributes['white_value'])
-
- def test_flash(self): \
- # pylint: disable=invalid-name
- """Test flash."""
- with assert_setup_component(1, light.DOMAIN):
- assert setup_component(self.hass, light.DOMAIN, {
- light.DOMAIN: {
- 'platform': 'mqtt_template',
- 'name': 'test',
- 'command_topic': 'test_light_rgb/set',
- 'command_on_template': 'on,{{ flash }}',
- 'command_off_template': 'off',
- 'qos': 0
- }
- })
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_OFF, state.state)
-
- # short flash
- light.turn_on(self.hass, 'light.test', flash='short')
- self.hass.block_till_done()
-
- self.mock_publish.async_publish.assert_called_once_with(
- 'test_light_rgb/set', 'on,short', 0, False)
- self.mock_publish.async_publish.reset_mock()
-
- # long flash
- light.turn_on(self.hass, 'light.test', flash='long')
- self.hass.block_till_done()
-
- self.mock_publish.async_publish.assert_called_once_with(
- 'test_light_rgb/set', 'on,long', 0, False)
-
- def test_transition(self):
- """Test for transition time being sent when included."""
- with assert_setup_component(1, light.DOMAIN):
- assert setup_component(self.hass, light.DOMAIN, {
- light.DOMAIN: {
- 'platform': 'mqtt_template',
- 'name': 'test',
- 'command_topic': 'test_light_rgb/set',
- 'command_on_template': 'on,{{ transition }}',
- 'command_off_template': 'off,{{ transition|d }}'
- }
- })
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_OFF, state.state)
-
- # transition on
- light.turn_on(self.hass, 'light.test', transition=10)
- self.hass.block_till_done()
-
- self.mock_publish.async_publish.assert_called_once_with(
- 'test_light_rgb/set', 'on,10', 0, False)
- self.mock_publish.async_publish.reset_mock()
-
- # transition off
- light.turn_off(self.hass, 'light.test', transition=4)
- self.hass.block_till_done()
-
- self.mock_publish.async_publish.assert_called_once_with(
- 'test_light_rgb/set', 'off,4', 0, False)
-
- def test_invalid_values(self): \
- # pylint: disable=invalid-name
- """Test that invalid values are ignored."""
- with assert_setup_component(1, light.DOMAIN):
- assert setup_component(self.hass, light.DOMAIN, {
- light.DOMAIN: {
- 'platform': 'mqtt_template',
- 'name': 'test',
- 'effect_list': ['rainbow', 'colorloop'],
- 'state_topic': 'test_light_rgb',
- 'command_topic': 'test_light_rgb/set',
- 'command_on_template': 'on,'
- '{{ brightness|d }},'
- '{{ color_temp|d }},'
- '{{ red|d }}-'
- '{{ green|d }}-'
- '{{ blue|d }},'
- '{{ effect|d }}',
- 'command_off_template': 'off',
- 'state_template': '{{ value.split(",")[0] }}',
- 'brightness_template': '{{ value.split(",")[1] }}',
- 'color_temp_template': '{{ value.split(",")[2] }}',
- 'white_value_template': '{{ value.split(",")[3] }}',
- 'red_template': '{{ value.split(",")[4].'
- 'split("-")[0] }}',
- 'green_template': '{{ value.split(",")[4].'
- 'split("-")[1] }}',
- 'blue_template': '{{ value.split(",")[4].'
- 'split("-")[2] }}',
- 'effect_template': '{{ value.split(",")[5] }}',
- }
- })
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_OFF, state.state)
- self.assertIsNone(state.attributes.get('rgb_color'))
- self.assertIsNone(state.attributes.get('brightness'))
- self.assertIsNone(state.attributes.get('color_temp'))
- self.assertIsNone(state.attributes.get('effect'))
- self.assertIsNone(state.attributes.get('white_value'))
- self.assertFalse(state.attributes.get(ATTR_ASSUMED_STATE))
-
- # turn on the light, full white
- fire_mqtt_message(self.hass, 'test_light_rgb',
- 'on,255,215,222,255-255-255,rainbow')
- self.hass.block_till_done()
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_ON, state.state)
- self.assertEqual(255, state.attributes.get('brightness'))
- self.assertEqual(215, state.attributes.get('color_temp'))
- self.assertEqual([255, 255, 255], state.attributes.get('rgb_color'))
- self.assertEqual(222, state.attributes.get('white_value'))
- self.assertEqual('rainbow', state.attributes.get('effect'))
-
- # bad state value
- fire_mqtt_message(self.hass, 'test_light_rgb', 'offf')
- self.hass.block_till_done()
-
- # state should not have changed
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_ON, state.state)
-
- # bad brightness values
- fire_mqtt_message(self.hass, 'test_light_rgb', 'on,off,255-255-255')
- self.hass.block_till_done()
-
- # brightness should not have changed
- state = self.hass.states.get('light.test')
- self.assertEqual(255, state.attributes.get('brightness'))
-
- # bad color temp values
- fire_mqtt_message(self.hass, 'test_light_rgb', 'on,,off,255-255-255')
- self.hass.block_till_done()
-
- # color temp should not have changed
- state = self.hass.states.get('light.test')
- self.assertEqual(215, state.attributes.get('color_temp'))
-
- # bad color values
- fire_mqtt_message(self.hass, 'test_light_rgb', 'on,255,a-b-c')
- self.hass.block_till_done()
-
- # color should not have changed
- state = self.hass.states.get('light.test')
- self.assertEqual([255, 255, 255], state.attributes.get('rgb_color'))
-
- # bad white value values
- fire_mqtt_message(self.hass, 'test_light_rgb', 'on,,,off,255-255-255')
- self.hass.block_till_done()
-
- # white value should not have changed
- state = self.hass.states.get('light.test')
- self.assertEqual(222, state.attributes.get('white_value'))
-
- # bad effect value
- fire_mqtt_message(self.hass, 'test_light_rgb', 'on,255,a-b-c,white')
- self.hass.block_till_done()
-
- # effect should not have changed
- state = self.hass.states.get('light.test')
- self.assertEqual('rainbow', state.attributes.get('effect'))
-
- def test_default_availability_payload(self):
- """Test availability by default payload with defined topic."""
- self.assertTrue(setup_component(self.hass, light.DOMAIN, {
- light.DOMAIN: {
- 'platform': 'mqtt_template',
- 'name': 'test',
- 'command_topic': 'test_light_rgb/set',
- 'command_on_template': 'on,{{ transition }}',
- 'command_off_template': 'off,{{ transition|d }}',
- 'availability_topic': 'availability-topic'
- }
- }))
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_UNAVAILABLE, state.state)
-
- fire_mqtt_message(self.hass, 'availability-topic', 'online')
- self.hass.block_till_done()
-
- state = self.hass.states.get('light.test')
- self.assertNotEqual(STATE_UNAVAILABLE, state.state)
-
- fire_mqtt_message(self.hass, 'availability-topic', 'offline')
- self.hass.block_till_done()
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_UNAVAILABLE, state.state)
-
- def test_custom_availability_payload(self):
- """Test availability by custom payload with defined topic."""
- self.assertTrue(setup_component(self.hass, light.DOMAIN, {
- light.DOMAIN: {
- 'platform': 'mqtt_template',
- 'name': 'test',
- 'command_topic': 'test_light_rgb/set',
- 'command_on_template': 'on,{{ transition }}',
- 'command_off_template': 'off,{{ transition|d }}',
- 'availability_topic': 'availability-topic',
- 'payload_available': 'good',
- 'payload_not_available': 'nogood'
- }
- }))
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_UNAVAILABLE, state.state)
-
- fire_mqtt_message(self.hass, 'availability-topic', 'good')
- self.hass.block_till_done()
-
- state = self.hass.states.get('light.test')
- self.assertNotEqual(STATE_UNAVAILABLE, state.state)
-
- fire_mqtt_message(self.hass, 'availability-topic', 'nogood')
- self.hass.block_till_done()
-
- state = self.hass.states.get('light.test')
- self.assertEqual(STATE_UNAVAILABLE, state.state)
+"""The tests for the MQTT Template light platform.
+
+Configuration example with all features:
+
+light:
+ platform: mqtt_template
+ name: mqtt_template_light_1
+ state_topic: 'home/rgb1'
+ command_topic: 'home/rgb1/set'
+ command_on_template: >
+ on,{{ brightness|d }},{{ red|d }}-{{ green|d }}-{{ blue|d }}
+ command_off_template: 'off'
+ state_template: '{{ value.split(",")[0] }}'
+ brightness_template: '{{ value.split(",")[1] }}'
+ color_temp_template: '{{ value.split(",")[2] }}'
+ white_value_template: '{{ value.split(",")[3] }}'
+ red_template: '{{ value.split(",")[4].split("-")[0] }}'
+ green_template: '{{ value.split(",")[4].split("-")[1] }}'
+ blue_template: '{{ value.split(",")[4].split("-")[2] }}'
+
+If your light doesn't support brightness feature, omit `brightness_template`.
+
+If your light doesn't support color temp feature, omit `color_temp_template`.
+
+If your light doesn't support white value feature, omit `white_value_template`.
+
+If your light doesn't support RGB feature, omit `(red|green|blue)_template`.
+"""
+import unittest
+
+from homeassistant.setup import setup_component
+from homeassistant.const import (
+ STATE_ON, STATE_OFF, STATE_UNAVAILABLE, ATTR_ASSUMED_STATE)
+import homeassistant.components.light as light
+from tests.common import (
+ get_test_home_assistant, mock_mqtt_component, fire_mqtt_message,
+ assert_setup_component)
+
+
+class TestLightMQTTTemplate(unittest.TestCase):
+ """Test the MQTT Template light."""
+
+ def setUp(self): # pylint: disable=invalid-name
+ """Setup things to be run when tests are started."""
+ self.hass = get_test_home_assistant()
+ self.mock_publish = mock_mqtt_component(self.hass)
+
+ def tearDown(self): # pylint: disable=invalid-name
+ """Stop everything that was started."""
+ self.hass.stop()
+
+ def test_setup_fails(self): \
+ # pylint: disable=invalid-name
+ """Test that setup fails with missing required configuration items."""
+ with assert_setup_component(0, light.DOMAIN):
+ assert setup_component(self.hass, light.DOMAIN, {
+ light.DOMAIN: {
+ 'platform': 'mqtt_template',
+ 'name': 'test',
+ }
+ })
+ self.assertIsNone(self.hass.states.get('light.test'))
+
+ def test_state_change_via_topic(self): \
+ # pylint: disable=invalid-name
+ """Test state change via topic."""
+ with assert_setup_component(1, light.DOMAIN):
+ assert setup_component(self.hass, light.DOMAIN, {
+ light.DOMAIN: {
+ 'platform': 'mqtt_template',
+ 'name': 'test',
+ 'state_topic': 'test_light_rgb',
+ 'command_topic': 'test_light_rgb/set',
+ 'command_on_template': 'on,'
+ '{{ brightness|d }},'
+ '{{ color_temp|d }},'
+ '{{ white_value|d }},'
+ '{{ red|d }}-'
+ '{{ green|d }}-'
+ '{{ blue|d }}',
+ 'command_off_template': 'off',
+ 'state_template': '{{ value.split(",")[0] }}'
+ }
+ })
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_OFF, state.state)
+ self.assertIsNone(state.attributes.get('rgb_color'))
+ self.assertIsNone(state.attributes.get('brightness'))
+ self.assertIsNone(state.attributes.get('color_temp'))
+ self.assertIsNone(state.attributes.get('white_value'))
+ self.assertFalse(state.attributes.get(ATTR_ASSUMED_STATE))
+
+ fire_mqtt_message(self.hass, 'test_light_rgb', 'on')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_ON, state.state)
+ self.assertIsNone(state.attributes.get('rgb_color'))
+ self.assertIsNone(state.attributes.get('brightness'))
+ self.assertIsNone(state.attributes.get('color_temp'))
+ self.assertIsNone(state.attributes.get('white_value'))
+
+ def test_state_brightness_color_effect_temp_white_change_via_topic(self): \
+ # pylint: disable=invalid-name
+ """Test state, bri, color, effect, color temp, white val change."""
+ with assert_setup_component(1, light.DOMAIN):
+ assert setup_component(self.hass, light.DOMAIN, {
+ light.DOMAIN: {
+ 'platform': 'mqtt_template',
+ 'name': 'test',
+ 'effect_list': ['rainbow', 'colorloop'],
+ 'state_topic': 'test_light_rgb',
+ 'command_topic': 'test_light_rgb/set',
+ 'command_on_template': 'on,'
+ '{{ brightness|d }},'
+ '{{ color_temp|d }},'
+ '{{ white_value|d }},'
+ '{{ red|d }}-'
+ '{{ green|d }}-'
+ '{{ blue|d }},'
+ '{{ effect|d }}',
+ 'command_off_template': 'off',
+ 'state_template': '{{ value.split(",")[0] }}',
+ 'brightness_template': '{{ value.split(",")[1] }}',
+ 'color_temp_template': '{{ value.split(",")[2] }}',
+ 'white_value_template': '{{ value.split(",")[3] }}',
+ 'red_template': '{{ value.split(",")[4].'
+ 'split("-")[0] }}',
+ 'green_template': '{{ value.split(",")[4].'
+ 'split("-")[1] }}',
+ 'blue_template': '{{ value.split(",")[4].'
+ 'split("-")[2] }}',
+ 'effect_template': '{{ value.split(",")[5] }}'
+ }
+ })
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_OFF, state.state)
+ self.assertIsNone(state.attributes.get('rgb_color'))
+ self.assertIsNone(state.attributes.get('brightness'))
+ self.assertIsNone(state.attributes.get('effect'))
+ self.assertIsNone(state.attributes.get('color_temp'))
+ self.assertIsNone(state.attributes.get('white_value'))
+ self.assertFalse(state.attributes.get(ATTR_ASSUMED_STATE))
+
+ # turn on the light, full white
+ fire_mqtt_message(self.hass, 'test_light_rgb',
+ 'on,255,145,123,255-128-64,')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_ON, state.state)
+ self.assertEqual([255, 128, 64], state.attributes.get('rgb_color'))
+ self.assertEqual(255, state.attributes.get('brightness'))
+ self.assertEqual(145, state.attributes.get('color_temp'))
+ self.assertEqual(123, state.attributes.get('white_value'))
+ self.assertIsNone(state.attributes.get('effect'))
+
+ # turn the light off
+ fire_mqtt_message(self.hass, 'test_light_rgb', 'off')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_OFF, state.state)
+
+ # lower the brightness
+ fire_mqtt_message(self.hass, 'test_light_rgb', 'on,100')
+ self.hass.block_till_done()
+
+ light_state = self.hass.states.get('light.test')
+ self.hass.block_till_done()
+ self.assertEqual(100, light_state.attributes['brightness'])
+
+ # change the color temp
+ fire_mqtt_message(self.hass, 'test_light_rgb', 'on,,195')
+ self.hass.block_till_done()
+
+ light_state = self.hass.states.get('light.test')
+ self.hass.block_till_done()
+ self.assertEqual(195, light_state.attributes['color_temp'])
+
+ # change the color
+ fire_mqtt_message(self.hass, 'test_light_rgb', 'on,,,,41-42-43')
+ self.hass.block_till_done()
+
+ light_state = self.hass.states.get('light.test')
+ self.assertEqual([41, 42, 43], light_state.attributes.get('rgb_color'))
+
+ # change the white value
+ fire_mqtt_message(self.hass, 'test_light_rgb', 'on,,,134')
+ self.hass.block_till_done()
+
+ light_state = self.hass.states.get('light.test')
+ self.hass.block_till_done()
+ self.assertEqual(134, light_state.attributes['white_value'])
+
+ # change the effect
+ fire_mqtt_message(self.hass, 'test_light_rgb',
+ 'on,,,,41-42-43,rainbow')
+ self.hass.block_till_done()
+
+ light_state = self.hass.states.get('light.test')
+ self.assertEqual('rainbow', light_state.attributes.get('effect'))
+
+ def test_optimistic(self): \
+ # pylint: disable=invalid-name
+ """Test optimistic mode."""
+ with assert_setup_component(1, light.DOMAIN):
+ assert setup_component(self.hass, light.DOMAIN, {
+ light.DOMAIN: {
+ 'platform': 'mqtt_template',
+ 'name': 'test',
+ 'command_topic': 'test_light_rgb/set',
+ 'command_on_template': 'on,'
+ '{{ brightness|d }},'
+ '{{ color_temp|d }},'
+ '{{ white_value|d }},'
+ '{{ red|d }}-'
+ '{{ green|d }}-'
+ '{{ blue|d }}',
+ 'command_off_template': 'off',
+ 'qos': 2
+ }
+ })
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_OFF, state.state)
+ self.assertTrue(state.attributes.get(ATTR_ASSUMED_STATE))
+
+ # turn on the light
+ light.turn_on(self.hass, 'light.test')
+ self.hass.block_till_done()
+
+ self.mock_publish.async_publish.assert_called_once_with(
+ 'test_light_rgb/set', 'on,,,,--', 2, False)
+ self.mock_publish.async_publish.reset_mock()
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_ON, state.state)
+
+ # turn the light off
+ light.turn_off(self.hass, 'light.test')
+ self.hass.block_till_done()
+
+ self.mock_publish.async_publish.assert_called_once_with(
+ 'test_light_rgb/set', 'off', 2, False)
+ self.mock_publish.async_publish.reset_mock()
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_OFF, state.state)
+
+ # turn on the light with brightness, color
+ light.turn_on(self.hass, 'light.test', brightness=50,
+ rgb_color=[75, 75, 75])
+ self.hass.block_till_done()
+
+ self.mock_publish.async_publish.assert_called_once_with(
+ 'test_light_rgb/set', 'on,50,,,75-75-75', 2, False)
+ self.mock_publish.async_publish.reset_mock()
+
+ # turn on the light with color temp and white val
+ light.turn_on(self.hass, 'light.test', color_temp=200, white_value=139)
+ self.hass.block_till_done()
+
+ self.mock_publish.async_publish.assert_called_once_with(
+ 'test_light_rgb/set', 'on,,200,139,--', 2, False)
+
+ # check the state
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_ON, state.state)
+ self.assertEqual((75, 75, 75), state.attributes['rgb_color'])
+ self.assertEqual(50, state.attributes['brightness'])
+ self.assertEqual(200, state.attributes['color_temp'])
+ self.assertEqual(139, state.attributes['white_value'])
+
+ def test_flash(self): \
+ # pylint: disable=invalid-name
+ """Test flash."""
+ with assert_setup_component(1, light.DOMAIN):
+ assert setup_component(self.hass, light.DOMAIN, {
+ light.DOMAIN: {
+ 'platform': 'mqtt_template',
+ 'name': 'test',
+ 'command_topic': 'test_light_rgb/set',
+ 'command_on_template': 'on,{{ flash }}',
+ 'command_off_template': 'off',
+ 'qos': 0
+ }
+ })
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_OFF, state.state)
+
+ # short flash
+ light.turn_on(self.hass, 'light.test', flash='short')
+ self.hass.block_till_done()
+
+ self.mock_publish.async_publish.assert_called_once_with(
+ 'test_light_rgb/set', 'on,short', 0, False)
+ self.mock_publish.async_publish.reset_mock()
+
+ # long flash
+ light.turn_on(self.hass, 'light.test', flash='long')
+ self.hass.block_till_done()
+
+ self.mock_publish.async_publish.assert_called_once_with(
+ 'test_light_rgb/set', 'on,long', 0, False)
+
+ def test_transition(self):
+ """Test for transition time being sent when included."""
+ with assert_setup_component(1, light.DOMAIN):
+ assert setup_component(self.hass, light.DOMAIN, {
+ light.DOMAIN: {
+ 'platform': 'mqtt_template',
+ 'name': 'test',
+ 'command_topic': 'test_light_rgb/set',
+ 'command_on_template': 'on,{{ transition }}',
+ 'command_off_template': 'off,{{ transition|d }}'
+ }
+ })
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_OFF, state.state)
+
+ # transition on
+ light.turn_on(self.hass, 'light.test', transition=10)
+ self.hass.block_till_done()
+
+ self.mock_publish.async_publish.assert_called_once_with(
+ 'test_light_rgb/set', 'on,10', 0, False)
+ self.mock_publish.async_publish.reset_mock()
+
+ # transition off
+ light.turn_off(self.hass, 'light.test', transition=4)
+ self.hass.block_till_done()
+
+ self.mock_publish.async_publish.assert_called_once_with(
+ 'test_light_rgb/set', 'off,4', 0, False)
+
+ def test_invalid_values(self): \
+ # pylint: disable=invalid-name
+ """Test that invalid values are ignored."""
+ with assert_setup_component(1, light.DOMAIN):
+ assert setup_component(self.hass, light.DOMAIN, {
+ light.DOMAIN: {
+ 'platform': 'mqtt_template',
+ 'name': 'test',
+ 'effect_list': ['rainbow', 'colorloop'],
+ 'state_topic': 'test_light_rgb',
+ 'command_topic': 'test_light_rgb/set',
+ 'command_on_template': 'on,'
+ '{{ brightness|d }},'
+ '{{ color_temp|d }},'
+ '{{ red|d }}-'
+ '{{ green|d }}-'
+ '{{ blue|d }},'
+ '{{ effect|d }}',
+ 'command_off_template': 'off',
+ 'state_template': '{{ value.split(",")[0] }}',
+ 'brightness_template': '{{ value.split(",")[1] }}',
+ 'color_temp_template': '{{ value.split(",")[2] }}',
+ 'white_value_template': '{{ value.split(",")[3] }}',
+ 'red_template': '{{ value.split(",")[4].'
+ 'split("-")[0] }}',
+ 'green_template': '{{ value.split(",")[4].'
+ 'split("-")[1] }}',
+ 'blue_template': '{{ value.split(",")[4].'
+ 'split("-")[2] }}',
+ 'effect_template': '{{ value.split(",")[5] }}',
+ }
+ })
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_OFF, state.state)
+ self.assertIsNone(state.attributes.get('rgb_color'))
+ self.assertIsNone(state.attributes.get('brightness'))
+ self.assertIsNone(state.attributes.get('color_temp'))
+ self.assertIsNone(state.attributes.get('effect'))
+ self.assertIsNone(state.attributes.get('white_value'))
+ self.assertFalse(state.attributes.get(ATTR_ASSUMED_STATE))
+
+ # turn on the light, full white
+ fire_mqtt_message(self.hass, 'test_light_rgb',
+ 'on,255,215,222,255-255-255,rainbow')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_ON, state.state)
+ self.assertEqual(255, state.attributes.get('brightness'))
+ self.assertEqual(215, state.attributes.get('color_temp'))
+ self.assertEqual([255, 255, 255], state.attributes.get('rgb_color'))
+ self.assertEqual(222, state.attributes.get('white_value'))
+ self.assertEqual('rainbow', state.attributes.get('effect'))
+
+ # bad state value
+ fire_mqtt_message(self.hass, 'test_light_rgb', 'offf')
+ self.hass.block_till_done()
+
+ # state should not have changed
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_ON, state.state)
+
+ # bad brightness values
+ fire_mqtt_message(self.hass, 'test_light_rgb', 'on,off,255-255-255')
+ self.hass.block_till_done()
+
+ # brightness should not have changed
+ state = self.hass.states.get('light.test')
+ self.assertEqual(255, state.attributes.get('brightness'))
+
+ # bad color temp values
+ fire_mqtt_message(self.hass, 'test_light_rgb', 'on,,off,255-255-255')
+ self.hass.block_till_done()
+
+ # color temp should not have changed
+ state = self.hass.states.get('light.test')
+ self.assertEqual(215, state.attributes.get('color_temp'))
+
+ # bad color values
+ fire_mqtt_message(self.hass, 'test_light_rgb', 'on,255,a-b-c')
+ self.hass.block_till_done()
+
+ # color should not have changed
+ state = self.hass.states.get('light.test')
+ self.assertEqual([255, 255, 255], state.attributes.get('rgb_color'))
+
+ # bad white value values
+ fire_mqtt_message(self.hass, 'test_light_rgb', 'on,,,off,255-255-255')
+ self.hass.block_till_done()
+
+ # white value should not have changed
+ state = self.hass.states.get('light.test')
+ self.assertEqual(222, state.attributes.get('white_value'))
+
+ # bad effect value
+ fire_mqtt_message(self.hass, 'test_light_rgb', 'on,255,a-b-c,white')
+ self.hass.block_till_done()
+
+ # effect should not have changed
+ state = self.hass.states.get('light.test')
+ self.assertEqual('rainbow', state.attributes.get('effect'))
+
+ def test_default_availability_payload(self):
+ """Test availability by default payload with defined topic."""
+ self.assertTrue(setup_component(self.hass, light.DOMAIN, {
+ light.DOMAIN: {
+ 'platform': 'mqtt_template',
+ 'name': 'test',
+ 'command_topic': 'test_light_rgb/set',
+ 'command_on_template': 'on,{{ transition }}',
+ 'command_off_template': 'off,{{ transition|d }}',
+ 'availability_topic': 'availability-topic'
+ }
+ }))
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_UNAVAILABLE, state.state)
+
+ fire_mqtt_message(self.hass, 'availability-topic', 'online')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('light.test')
+ self.assertNotEqual(STATE_UNAVAILABLE, state.state)
+
+ fire_mqtt_message(self.hass, 'availability-topic', 'offline')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_UNAVAILABLE, state.state)
+
+ def test_custom_availability_payload(self):
+ """Test availability by custom payload with defined topic."""
+ self.assertTrue(setup_component(self.hass, light.DOMAIN, {
+ light.DOMAIN: {
+ 'platform': 'mqtt_template',
+ 'name': 'test',
+ 'command_topic': 'test_light_rgb/set',
+ 'command_on_template': 'on,{{ transition }}',
+ 'command_off_template': 'off,{{ transition|d }}',
+ 'availability_topic': 'availability-topic',
+ 'payload_available': 'good',
+ 'payload_not_available': 'nogood'
+ }
+ }))
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_UNAVAILABLE, state.state)
+
+ fire_mqtt_message(self.hass, 'availability-topic', 'good')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('light.test')
+ self.assertNotEqual(STATE_UNAVAILABLE, state.state)
+
+ fire_mqtt_message(self.hass, 'availability-topic', 'nogood')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('light.test')
+ self.assertEqual(STATE_UNAVAILABLE, state.state)
diff --git a/tests/fixtures/pushbullet_devices.json b/tests/fixtures/pushbullet_devices.json
index 04f336c8adf4d9..576e748471acb8 100755
--- a/tests/fixtures/pushbullet_devices.json
+++ b/tests/fixtures/pushbullet_devices.json
@@ -1,43 +1,43 @@
-{
- "accounts": [],
- "blocks": [],
- "channels": [],
- "chats": [],
- "clients": [],
- "contacts": [],
- "devices": [{
- "active": true,
- "iden": "identity1",
- "created": 1.514520333770855e+09,
- "modified": 1.5151951594363022e+09,
- "type": "windows",
- "kind": "windows",
- "nickname": "DESKTOP",
- "manufacturer": "Microsoft",
- "model": "Windows 10 Home",
- "app_version": 396,
- "fingerprint": "{\"cpu\":\"AMD\",\"computer_name\":\"DESKTOP\"}",
- "pushable": true,
- "icon": "desktop",
- "remote_files": "disabled"
- }, {
- "active": true,
- "iden": "identity2",
- "created": 1.5144974875448499e+09,
- "modified": 1.514574792288634e+09,
- "type": "ios",
- "kind": "ios",
- "nickname": "My iPhone",
- "manufacturer": "Apple",
- "model": "iPhone",
- "app_version": 8646,
- "push_token": "production:mytoken",
- "pushable": true,
- "icon": "phone"
- }],
- "grants": [],
- "pushes": [],
- "profiles": [],
- "subscriptions": [],
- "texts": []
-}
+{
+ "accounts": [],
+ "blocks": [],
+ "channels": [],
+ "chats": [],
+ "clients": [],
+ "contacts": [],
+ "devices": [{
+ "active": true,
+ "iden": "identity1",
+ "created": 1.514520333770855e+09,
+ "modified": 1.5151951594363022e+09,
+ "type": "windows",
+ "kind": "windows",
+ "nickname": "DESKTOP",
+ "manufacturer": "Microsoft",
+ "model": "Windows 10 Home",
+ "app_version": 396,
+ "fingerprint": "{\"cpu\":\"AMD\",\"computer_name\":\"DESKTOP\"}",
+ "pushable": true,
+ "icon": "desktop",
+ "remote_files": "disabled"
+ }, {
+ "active": true,
+ "iden": "identity2",
+ "created": 1.5144974875448499e+09,
+ "modified": 1.514574792288634e+09,
+ "type": "ios",
+ "kind": "ios",
+ "nickname": "My iPhone",
+ "manufacturer": "Apple",
+ "model": "iPhone",
+ "app_version": 8646,
+ "push_token": "production:mytoken",
+ "pushable": true,
+ "icon": "phone"
+ }],
+ "grants": [],
+ "pushes": [],
+ "profiles": [],
+ "subscriptions": [],
+ "texts": []
+}
diff --git a/tests/fixtures/yahooweather.json b/tests/fixtures/yahooweather.json
index f6ab2980618865..7d8188764dfa10 100644
--- a/tests/fixtures/yahooweather.json
+++ b/tests/fixtures/yahooweather.json
@@ -1,138 +1,138 @@
-{
- "query": {
- "count": 1,
- "created": "2017-11-17T13:40:47Z",
- "lang": "en-US",
- "results": {
- "channel": {
- "units": {
- "distance": "km",
- "pressure": "mb",
- "speed": "km/h",
- "temperature": "C"
- },
- "title": "Yahoo! Weather - San Diego, CA, US",
- "link": "http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-23511632/",
- "description": "Yahoo! Weather for San Diego, CA, US",
- "language": "en-us",
- "lastBuildDate": "Fri, 17 Nov 2017 05:40 AM PST",
- "ttl": "60",
- "location": {
- "city": "San Diego",
- "country": "United States",
- "region": " CA"
- },
- "wind": {
- "chill": "56",
- "direction": "0",
- "speed": "6.34"
- },
- "atmosphere": {
- "humidity": "71",
- "pressure": "33863.75",
- "rising": "0",
- "visibility": "22.91"
- },
- "astronomy": {
- "sunrise": "6:21 am",
- "sunset": "4:47 pm"
- },
- "image": {
- "title": "Yahoo! Weather",
- "width": "142",
- "height": "18",
- "link": "http://weather.yahoo.com",
- "url": "http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif"
- },
- "item": {
- "title": "Conditions for San Diego, CA, US at 05:00 AM PST",
- "lat": "32.878101",
- "long": "-117.23497",
- "link": "http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-23511632/",
- "pubDate": "Fri, 17 Nov 2017 05:00 AM PST",
- "condition": {
- "code": "26",
- "date": "Fri, 17 Nov 2017 05:00 AM PST",
- "temp": "18",
- "text": "Cloudy"
- },
- "forecast": [{
- "code": "28",
- "date": "17 Nov 2017",
- "day": "Fri",
- "high": "23",
- "low": "16",
- "text": "Mostly Cloudy"
- }, {
- "code": "30",
- "date": "18 Nov 2017",
- "day": "Sat",
- "high": "22",
- "low": "13",
- "text": "Partly Cloudy"
- }, {
- "code": "30",
- "date": "19 Nov 2017",
- "day": "Sun",
- "high": "22",
- "low": "12",
- "text": "Partly Cloudy"
- }, {
- "code": "28",
- "date": "20 Nov 2017",
- "day": "Mon",
- "high": "21",
- "low": "11",
- "text": "Mostly Cloudy"
- }, {
- "code": "28",
- "date": "21 Nov 2017",
- "day": "Tue",
- "high": "24",
- "low": "14",
- "text": "Mostly Cloudy"
- }, {
- "code": "30",
- "date": "22 Nov 2017",
- "day": "Wed",
- "high": "27",
- "low": "15",
- "text": "Partly Cloudy"
- }, {
- "code": "34",
- "date": "23 Nov 2017",
- "day": "Thu",
- "high": "27",
- "low": "15",
- "text": "Mostly Sunny"
- }, {
- "code": "30",
- "date": "24 Nov 2017",
- "day": "Fri",
- "high": "23",
- "low": "16",
- "text": "Partly Cloudy"
- }, {
- "code": "30",
- "date": "25 Nov 2017",
- "day": "Sat",
- "high": "22",
- "low": "15",
- "text": "Partly Cloudy"
- }, {
- "code": "28",
- "date": "26 Nov 2017",
- "day": "Sun",
- "high": "24",
- "low": "13",
- "text": "Mostly Cloudy"
- }],
- "description": "\n
\nCurrent Conditions:\n
Cloudy\n
\n
\nForecast:\n
Fri - Mostly Cloudy. High: 23Low: 16\n
Sat - Partly Cloudy. High: 22Low: 13\n
Sun - Partly Cloudy. High: 22Low: 12\n
Mon - Mostly Cloudy. High: 21Low: 11\n
Tue - Mostly Cloudy. High: 24Low: 14\n
\n
\nFull Forecast at Yahoo! Weather\n
\n
\n
\n]]>",
- "guid": {
- "isPermaLink": "false"
- }
- }
- }
- }
- }
-}
+{
+ "query": {
+ "count": 1,
+ "created": "2017-11-17T13:40:47Z",
+ "lang": "en-US",
+ "results": {
+ "channel": {
+ "units": {
+ "distance": "km",
+ "pressure": "mb",
+ "speed": "km/h",
+ "temperature": "C"
+ },
+ "title": "Yahoo! Weather - San Diego, CA, US",
+ "link": "http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-23511632/",
+ "description": "Yahoo! Weather for San Diego, CA, US",
+ "language": "en-us",
+ "lastBuildDate": "Fri, 17 Nov 2017 05:40 AM PST",
+ "ttl": "60",
+ "location": {
+ "city": "San Diego",
+ "country": "United States",
+ "region": " CA"
+ },
+ "wind": {
+ "chill": "56",
+ "direction": "0",
+ "speed": "6.34"
+ },
+ "atmosphere": {
+ "humidity": "71",
+ "pressure": "33863.75",
+ "rising": "0",
+ "visibility": "22.91"
+ },
+ "astronomy": {
+ "sunrise": "6:21 am",
+ "sunset": "4:47 pm"
+ },
+ "image": {
+ "title": "Yahoo! Weather",
+ "width": "142",
+ "height": "18",
+ "link": "http://weather.yahoo.com",
+ "url": "http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif"
+ },
+ "item": {
+ "title": "Conditions for San Diego, CA, US at 05:00 AM PST",
+ "lat": "32.878101",
+ "long": "-117.23497",
+ "link": "http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-23511632/",
+ "pubDate": "Fri, 17 Nov 2017 05:00 AM PST",
+ "condition": {
+ "code": "26",
+ "date": "Fri, 17 Nov 2017 05:00 AM PST",
+ "temp": "18",
+ "text": "Cloudy"
+ },
+ "forecast": [{
+ "code": "28",
+ "date": "17 Nov 2017",
+ "day": "Fri",
+ "high": "23",
+ "low": "16",
+ "text": "Mostly Cloudy"
+ }, {
+ "code": "30",
+ "date": "18 Nov 2017",
+ "day": "Sat",
+ "high": "22",
+ "low": "13",
+ "text": "Partly Cloudy"
+ }, {
+ "code": "30",
+ "date": "19 Nov 2017",
+ "day": "Sun",
+ "high": "22",
+ "low": "12",
+ "text": "Partly Cloudy"
+ }, {
+ "code": "28",
+ "date": "20 Nov 2017",
+ "day": "Mon",
+ "high": "21",
+ "low": "11",
+ "text": "Mostly Cloudy"
+ }, {
+ "code": "28",
+ "date": "21 Nov 2017",
+ "day": "Tue",
+ "high": "24",
+ "low": "14",
+ "text": "Mostly Cloudy"
+ }, {
+ "code": "30",
+ "date": "22 Nov 2017",
+ "day": "Wed",
+ "high": "27",
+ "low": "15",
+ "text": "Partly Cloudy"
+ }, {
+ "code": "34",
+ "date": "23 Nov 2017",
+ "day": "Thu",
+ "high": "27",
+ "low": "15",
+ "text": "Mostly Sunny"
+ }, {
+ "code": "30",
+ "date": "24 Nov 2017",
+ "day": "Fri",
+ "high": "23",
+ "low": "16",
+ "text": "Partly Cloudy"
+ }, {
+ "code": "30",
+ "date": "25 Nov 2017",
+ "day": "Sat",
+ "high": "22",
+ "low": "15",
+ "text": "Partly Cloudy"
+ }, {
+ "code": "28",
+ "date": "26 Nov 2017",
+ "day": "Sun",
+ "high": "24",
+ "low": "13",
+ "text": "Mostly Cloudy"
+ }],
+ "description": "\n
\nCurrent Conditions:\n
Cloudy\n
\n
\nForecast:\n
Fri - Mostly Cloudy. High: 23Low: 16\n
Sat - Partly Cloudy. High: 22Low: 13\n
Sun - Partly Cloudy. High: 22Low: 12\n
Mon - Mostly Cloudy. High: 21Low: 11\n
Tue - Mostly Cloudy. High: 24Low: 14\n
\n
\nFull Forecast at Yahoo! Weather\n
\n
\n
\n]]>",
+ "guid": {
+ "isPermaLink": "false"
+ }
+ }
+ }
+ }
+ }
+}