diff --git a/homeassistant/components/binary_sensor/mercedesme.py b/homeassistant/components/binary_sensor/mercedesme.py
old mode 100755
new mode 100644
index c817447f181..a6c8da56ce8
--- a/homeassistant/components/binary_sensor/mercedesme.py
+++ b/homeassistant/components/binary_sensor/mercedesme.py
@@ -1,94 +1,94 @@
-"""
-Support for Mercedes cars with Mercedes ME.
-
-For more details about this component, please refer to the documentation at
-https://home-assistant.io/components/binary_sensor.mercedesme/
-"""
-import logging
-import datetime
-
-from homeassistant.components.binary_sensor import (BinarySensorDevice)
-from homeassistant.components.mercedesme import (
- DATA_MME, MercedesMeEntity, BINARY_SENSORS)
-
-DEPENDENCIES = ['mercedesme']
-
-_LOGGER = logging.getLogger(__name__)
-
-
-def setup_platform(hass, config, add_devices, discovery_info=None):
- """Setup the sensor platform."""
- data = hass.data[DATA_MME].data
-
- if not data.cars:
- _LOGGER.error("No cars found. Check component log.")
- return
-
- devices = []
- for car in data.cars:
- for key, value in sorted(BINARY_SENSORS.items()):
- devices.append(MercedesMEBinarySensor(
- data, key, value[0], car["vin"], None))
-
- add_devices(devices, True)
-
-
-class MercedesMEBinarySensor(MercedesMeEntity, BinarySensorDevice):
- """Representation of a Sensor."""
-
- @property
- def is_on(self):
- """Return the state of the binary sensor."""
- return self._state
-
- @property
- def device_state_attributes(self):
- """Return the state attributes."""
- if self._internal_name == "windowsClosed":
- return {
- "window_front_left": self._car["windowStatusFrontLeft"],
- "window_front_right": self._car["windowStatusFrontRight"],
- "window_rear_left": self._car["windowStatusRearLeft"],
- "window_rear_right": self._car["windowStatusRearRight"],
- "original_value": self._car[self._internal_name],
- "last_update": datetime.datetime.fromtimestamp(
- self._car["lastUpdate"]).strftime('%Y-%m-%d %H:%M:%S'),
- "car": self._car["license"]
- }
- elif self._internal_name == "tireWarningLight":
- return {
- "front_right_tire_pressure_kpa":
- self._car["frontRightTirePressureKpa"],
- "front_left_tire_pressure_kpa":
- self._car["frontLeftTirePressureKpa"],
- "rear_right_tire_pressure_kpa":
- self._car["rearRightTirePressureKpa"],
- "rear_left_tire_pressure_kpa":
- self._car["rearLeftTirePressureKpa"],
- "original_value": self._car[self._internal_name],
- "last_update": datetime.datetime.fromtimestamp(
- self._car["lastUpdate"]
- ).strftime('%Y-%m-%d %H:%M:%S'),
- "car": self._car["license"],
- }
- return {
- "original_value": self._car[self._internal_name],
- "last_update": datetime.datetime.fromtimestamp(
- self._car["lastUpdate"]).strftime('%Y-%m-%d %H:%M:%S'),
- "car": self._car["license"]
- }
-
- def update(self):
- """Fetch new state data for the sensor."""
- self._car = next(
- car for car in self._data.cars if car["vin"] == self._vin)
-
- if self._internal_name == "windowsClosed":
- self._state = bool(self._car[self._internal_name] == "CLOSED")
- elif self._internal_name == "tireWarningLight":
- self._state = bool(self._car[self._internal_name] != "INACTIVE")
- else:
- self._state = self._car[self._internal_name] is True
-
- _LOGGER.debug("Updated %s Value: %s IsOn: %s",
- self._internal_name, self._state, self.is_on)
+"""
+Support for Mercedes cars with Mercedes ME.
+
+For more details about this component, please refer to the documentation at
+https://home-assistant.io/components/binary_sensor.mercedesme/
+"""
+import logging
+import datetime
+
+from homeassistant.components.binary_sensor import (BinarySensorDevice)
+from homeassistant.components.mercedesme import (
+ DATA_MME, MercedesMeEntity, BINARY_SENSORS)
+
+DEPENDENCIES = ['mercedesme']
+
+_LOGGER = logging.getLogger(__name__)
+
+
+def setup_platform(hass, config, add_devices, discovery_info=None):
+ """Setup the sensor platform."""
+ data = hass.data[DATA_MME].data
+
+ if not data.cars:
+ _LOGGER.error("No cars found. Check component log.")
+ return
+
+ devices = []
+ for car in data.cars:
+ for key, value in sorted(BINARY_SENSORS.items()):
+ devices.append(MercedesMEBinarySensor(
+ data, key, value[0], car["vin"], None))
+
+ add_devices(devices, True)
+
+
+class MercedesMEBinarySensor(MercedesMeEntity, BinarySensorDevice):
+ """Representation of a Sensor."""
+
+ @property
+ def is_on(self):
+ """Return the state of the binary sensor."""
+ return self._state
+
+ @property
+ def device_state_attributes(self):
+ """Return the state attributes."""
+ if self._internal_name == "windowsClosed":
+ return {
+ "window_front_left": self._car["windowStatusFrontLeft"],
+ "window_front_right": self._car["windowStatusFrontRight"],
+ "window_rear_left": self._car["windowStatusRearLeft"],
+ "window_rear_right": self._car["windowStatusRearRight"],
+ "original_value": self._car[self._internal_name],
+ "last_update": datetime.datetime.fromtimestamp(
+ self._car["lastUpdate"]).strftime('%Y-%m-%d %H:%M:%S'),
+ "car": self._car["license"]
+ }
+ elif self._internal_name == "tireWarningLight":
+ return {
+ "front_right_tire_pressure_kpa":
+ self._car["frontRightTirePressureKpa"],
+ "front_left_tire_pressure_kpa":
+ self._car["frontLeftTirePressureKpa"],
+ "rear_right_tire_pressure_kpa":
+ self._car["rearRightTirePressureKpa"],
+ "rear_left_tire_pressure_kpa":
+ self._car["rearLeftTirePressureKpa"],
+ "original_value": self._car[self._internal_name],
+ "last_update": datetime.datetime.fromtimestamp(
+ self._car["lastUpdate"]
+ ).strftime('%Y-%m-%d %H:%M:%S'),
+ "car": self._car["license"],
+ }
+ return {
+ "original_value": self._car[self._internal_name],
+ "last_update": datetime.datetime.fromtimestamp(
+ self._car["lastUpdate"]).strftime('%Y-%m-%d %H:%M:%S'),
+ "car": self._car["license"]
+ }
+
+ def update(self):
+ """Fetch new state data for the sensor."""
+ self._car = next(
+ car for car in self._data.cars if car["vin"] == self._vin)
+
+ if self._internal_name == "windowsClosed":
+ self._state = bool(self._car[self._internal_name] == "CLOSED")
+ elif self._internal_name == "tireWarningLight":
+ self._state = bool(self._car[self._internal_name] != "INACTIVE")
+ else:
+ self._state = self._car[self._internal_name] is True
+
+ _LOGGER.debug("Updated %s Value: %s IsOn: %s",
+ self._internal_name, self._state, self.is_on)
diff --git a/homeassistant/components/camera/xeoma.py b/homeassistant/components/camera/xeoma.py
old mode 100755
new mode 100644
diff --git a/homeassistant/components/device_tracker/mercedesme.py b/homeassistant/components/device_tracker/mercedesme.py
old mode 100755
new mode 100644
index ed516b738cc..0aa2be96290
--- a/homeassistant/components/device_tracker/mercedesme.py
+++ b/homeassistant/components/device_tracker/mercedesme.py
@@ -1,71 +1,71 @@
-"""
-Support for Mercedes cars with Mercedes ME.
-
-For more details about this component, please refer to the documentation at
-https://home-assistant.io/components/device_tracker.mercedesme/
-"""
-import logging
-from datetime import timedelta
-
-from homeassistant.components.mercedesme import DATA_MME
-from homeassistant.helpers.event import track_time_interval
-from homeassistant.util import Throttle
-
-_LOGGER = logging.getLogger(__name__)
-
-DEPENDENCIES = ['mercedesme']
-
-MIN_TIME_BETWEEN_SCANS = timedelta(seconds=30)
-
-
-def setup_scanner(hass, config, see, discovery_info=None):
- """Set up the Mercedes ME tracker."""
- if discovery_info is None:
- return False
-
- data = hass.data[DATA_MME].data
-
- if not data.cars:
- return False
-
- MercedesMEDeviceTracker(hass, config, see, data)
-
- return True
-
-
-class MercedesMEDeviceTracker(object):
- """A class representing a Mercedes ME device tracker."""
-
- def __init__(self, hass, config, see, data):
- """Initialize the Mercedes ME device tracker."""
- self.see = see
- self.data = data
- self.update_info()
-
- track_time_interval(
- hass, self.update_info, MIN_TIME_BETWEEN_SCANS)
-
- @Throttle(MIN_TIME_BETWEEN_SCANS)
- def update_info(self, now=None):
- """Update the device info."""
- for device in self.data.cars:
- _LOGGER.debug("Updating %s", device["vin"])
- location = self.data.get_location(device["vin"])
- if location is None:
- return False
- dev_id = device["vin"]
- name = device["license"]
-
- lat = location['positionLat']['value']
- lon = location['positionLong']['value']
- attrs = {
- 'trackr_id': dev_id,
- 'id': dev_id,
- 'name': name
- }
- self.see(
- dev_id=dev_id, host_name=name,
- gps=(lat, lon), attributes=attrs
- )
-
- return True
+"""
+Support for Mercedes cars with Mercedes ME.
+
+For more details about this component, please refer to the documentation at
+https://home-assistant.io/components/device_tracker.mercedesme/
+"""
+import logging
+from datetime import timedelta
+
+from homeassistant.components.mercedesme import DATA_MME
+from homeassistant.helpers.event import track_time_interval
+from homeassistant.util import Throttle
+
+_LOGGER = logging.getLogger(__name__)
+
+DEPENDENCIES = ['mercedesme']
+
+MIN_TIME_BETWEEN_SCANS = timedelta(seconds=30)
+
+
+def setup_scanner(hass, config, see, discovery_info=None):
+ """Set up the Mercedes ME tracker."""
+ if discovery_info is None:
+ return False
+
+ data = hass.data[DATA_MME].data
+
+ if not data.cars:
+ return False
+
+ MercedesMEDeviceTracker(hass, config, see, data)
+
+ return True
+
+
+class MercedesMEDeviceTracker(object):
+ """A class representing a Mercedes ME device tracker."""
+
+ def __init__(self, hass, config, see, data):
+ """Initialize the Mercedes ME device tracker."""
+ self.see = see
+ self.data = data
+ self.update_info()
+
+ track_time_interval(
+ hass, self.update_info, MIN_TIME_BETWEEN_SCANS)
+
+ @Throttle(MIN_TIME_BETWEEN_SCANS)
+ def update_info(self, now=None):
+ """Update the device info."""
+ for device in self.data.cars:
+ _LOGGER.debug("Updating %s", device["vin"])
+ location = self.data.get_location(device["vin"])
+ if location is None:
+ return False
+ dev_id = device["vin"]
+ name = device["license"]
+
+ lat = location['positionLat']['value']
+ lon = location['positionLong']['value']
+ attrs = {
+ 'trackr_id': dev_id,
+ 'id': dev_id,
+ 'name': name
+ }
+ self.see(
+ dev_id=dev_id, host_name=name,
+ gps=(lat, lon), attributes=attrs
+ )
+
+ return True
diff --git a/homeassistant/components/mercedesme.py b/homeassistant/components/mercedesme.py
old mode 100755
new mode 100644
index 0ac58e9c62e..a228486e2c8
--- a/homeassistant/components/mercedesme.py
+++ b/homeassistant/components/mercedesme.py
@@ -1,154 +1,154 @@
-"""
-Support for MercedesME System.
-
-For more details about this component, please refer to the documentation at
-https://home-assistant.io/components/mercedesme/
-"""
-import asyncio
-import logging
-from datetime import timedelta
-
-import voluptuous as vol
-import homeassistant.helpers.config_validation as cv
-
-from homeassistant.const import (
- CONF_USERNAME, CONF_PASSWORD, CONF_SCAN_INTERVAL, LENGTH_KILOMETERS)
-from homeassistant.helpers import discovery
-from homeassistant.helpers.dispatcher import (
- async_dispatcher_connect, dispatcher_send)
-from homeassistant.helpers.entity import Entity
-from homeassistant.helpers.event import track_time_interval
-
-REQUIREMENTS = ['mercedesmejsonpy==0.1.2']
-
-_LOGGER = logging.getLogger(__name__)
-
-BINARY_SENSORS = {
- 'doorsClosed': ['Doors closed'],
- 'windowsClosed': ['Windows closed'],
- 'locked': ['Doors locked'],
- 'tireWarningLight': ['Tire Warning']
-}
-
-SENSORS = {
- 'fuelLevelPercent': ['Fuel Level', '%'],
- 'fuelRangeKm': ['Fuel Range', LENGTH_KILOMETERS],
- 'latestTrip': ['Latest Trip', None],
- 'odometerKm': ['Odometer', LENGTH_KILOMETERS],
- 'serviceIntervalDays': ['Next Service', 'days']
-}
-
-DATA_MME = 'mercedesme'
-DOMAIN = 'mercedesme'
-
-NOTIFICATION_ID = 'mercedesme_integration_notification'
-NOTIFICATION_TITLE = 'Mercedes me integration setup'
-
-SIGNAL_UPDATE_MERCEDESME = "mercedesme_update"
-
-
-CONFIG_SCHEMA = vol.Schema({
- DOMAIN: vol.Schema({
- vol.Required(CONF_USERNAME): cv.string,
- vol.Required(CONF_PASSWORD): cv.string,
- vol.Optional(CONF_SCAN_INTERVAL, default=30):
- vol.All(cv.positive_int, vol.Clamp(min=10))
- })
-}, extra=vol.ALLOW_EXTRA)
-
-
-def setup(hass, config):
- """Set up MercedesMe System."""
- from mercedesmejsonpy.controller import Controller
- from mercedesmejsonpy import Exceptions
-
- conf = config[DOMAIN]
- username = conf.get(CONF_USERNAME)
- password = conf.get(CONF_PASSWORD)
- scan_interval = conf.get(CONF_SCAN_INTERVAL)
-
- try:
- mercedesme_api = Controller(username, password, scan_interval)
- if not mercedesme_api.is_valid_session:
- raise Exceptions.MercedesMeException(500)
- hass.data[DATA_MME] = MercedesMeHub(mercedesme_api)
- except Exceptions.MercedesMeException as ex:
- if ex.code == 401:
- hass.components.persistent_notification.create(
- "Error:
Please check username and password."
- "You will need to restart Home Assistant after fixing.",
- title=NOTIFICATION_TITLE,
- notification_id=NOTIFICATION_ID)
- else:
- hass.components.persistent_notification.create(
- "Error:
Can't communicate with Mercedes me API.
"
- "Error code: {} Reason: {}"
- "You will need to restart Home Assistant after fixing."
- "".format(ex.code, ex.message),
- title=NOTIFICATION_TITLE,
- notification_id=NOTIFICATION_ID)
-
- _LOGGER.error("Unable to communicate with Mercedes me API: %s",
- ex.message)
- return False
-
- discovery.load_platform(hass, 'sensor', DOMAIN, {}, config)
- discovery.load_platform(hass, 'device_tracker', DOMAIN, {}, config)
- discovery.load_platform(hass, 'binary_sensor', DOMAIN, {}, config)
-
- def hub_refresh(event_time):
- """Call Mercedes me API to refresh information."""
- _LOGGER.info("Updating Mercedes me component.")
- hass.data[DATA_MME].data.update()
- dispatcher_send(hass, SIGNAL_UPDATE_MERCEDESME)
-
- track_time_interval(
- hass,
- hub_refresh,
- timedelta(seconds=scan_interval))
-
- return True
-
-
-class MercedesMeHub(object):
- """Representation of a base MercedesMe device."""
-
- def __init__(self, data):
- """Initialize the entity."""
- self.data = data
-
-
-class MercedesMeEntity(Entity):
- """Entity class for MercedesMe devices."""
-
- def __init__(self, data, internal_name, sensor_name, vin, unit):
- """Initialize the MercedesMe entity."""
- self._car = None
- self._data = data
- self._state = False
- self._name = sensor_name
- self._internal_name = internal_name
- self._unit = unit
- self._vin = vin
-
- @property
- def name(self):
- """Return the name of the sensor."""
- return self._name
-
- @asyncio.coroutine
- def async_added_to_hass(self):
- """Register callbacks."""
- async_dispatcher_connect(
- self.hass, SIGNAL_UPDATE_MERCEDESME, self._update_callback)
-
- def _update_callback(self):
- """Callback update method."""
- # If the method is made a callback this should be changed
- # to the async version. Check core.callback
- self.schedule_update_ha_state(True)
-
- @property
- def unit_of_measurement(self):
- """Return the unit of measurement."""
- return self._unit
+"""
+Support for MercedesME System.
+
+For more details about this component, please refer to the documentation at
+https://home-assistant.io/components/mercedesme/
+"""
+import asyncio
+import logging
+from datetime import timedelta
+
+import voluptuous as vol
+import homeassistant.helpers.config_validation as cv
+
+from homeassistant.const import (
+ CONF_USERNAME, CONF_PASSWORD, CONF_SCAN_INTERVAL, LENGTH_KILOMETERS)
+from homeassistant.helpers import discovery
+from homeassistant.helpers.dispatcher import (
+ async_dispatcher_connect, dispatcher_send)
+from homeassistant.helpers.entity import Entity
+from homeassistant.helpers.event import track_time_interval
+
+REQUIREMENTS = ['mercedesmejsonpy==0.1.2']
+
+_LOGGER = logging.getLogger(__name__)
+
+BINARY_SENSORS = {
+ 'doorsClosed': ['Doors closed'],
+ 'windowsClosed': ['Windows closed'],
+ 'locked': ['Doors locked'],
+ 'tireWarningLight': ['Tire Warning']
+}
+
+SENSORS = {
+ 'fuelLevelPercent': ['Fuel Level', '%'],
+ 'fuelRangeKm': ['Fuel Range', LENGTH_KILOMETERS],
+ 'latestTrip': ['Latest Trip', None],
+ 'odometerKm': ['Odometer', LENGTH_KILOMETERS],
+ 'serviceIntervalDays': ['Next Service', 'days']
+}
+
+DATA_MME = 'mercedesme'
+DOMAIN = 'mercedesme'
+
+NOTIFICATION_ID = 'mercedesme_integration_notification'
+NOTIFICATION_TITLE = 'Mercedes me integration setup'
+
+SIGNAL_UPDATE_MERCEDESME = "mercedesme_update"
+
+
+CONFIG_SCHEMA = vol.Schema({
+ DOMAIN: vol.Schema({
+ vol.Required(CONF_USERNAME): cv.string,
+ vol.Required(CONF_PASSWORD): cv.string,
+ vol.Optional(CONF_SCAN_INTERVAL, default=30):
+ vol.All(cv.positive_int, vol.Clamp(min=10))
+ })
+}, extra=vol.ALLOW_EXTRA)
+
+
+def setup(hass, config):
+ """Set up MercedesMe System."""
+ from mercedesmejsonpy.controller import Controller
+ from mercedesmejsonpy import Exceptions
+
+ conf = config[DOMAIN]
+ username = conf.get(CONF_USERNAME)
+ password = conf.get(CONF_PASSWORD)
+ scan_interval = conf.get(CONF_SCAN_INTERVAL)
+
+ try:
+ mercedesme_api = Controller(username, password, scan_interval)
+ if not mercedesme_api.is_valid_session:
+ raise Exceptions.MercedesMeException(500)
+ hass.data[DATA_MME] = MercedesMeHub(mercedesme_api)
+ except Exceptions.MercedesMeException as ex:
+ if ex.code == 401:
+ hass.components.persistent_notification.create(
+ "Error:
Please check username and password."
+ "You will need to restart Home Assistant after fixing.",
+ title=NOTIFICATION_TITLE,
+ notification_id=NOTIFICATION_ID)
+ else:
+ hass.components.persistent_notification.create(
+ "Error:
Can't communicate with Mercedes me API.
"
+ "Error code: {} Reason: {}"
+ "You will need to restart Home Assistant after fixing."
+ "".format(ex.code, ex.message),
+ title=NOTIFICATION_TITLE,
+ notification_id=NOTIFICATION_ID)
+
+ _LOGGER.error("Unable to communicate with Mercedes me API: %s",
+ ex.message)
+ return False
+
+ discovery.load_platform(hass, 'sensor', DOMAIN, {}, config)
+ discovery.load_platform(hass, 'device_tracker', DOMAIN, {}, config)
+ discovery.load_platform(hass, 'binary_sensor', DOMAIN, {}, config)
+
+ def hub_refresh(event_time):
+ """Call Mercedes me API to refresh information."""
+ _LOGGER.info("Updating Mercedes me component.")
+ hass.data[DATA_MME].data.update()
+ dispatcher_send(hass, SIGNAL_UPDATE_MERCEDESME)
+
+ track_time_interval(
+ hass,
+ hub_refresh,
+ timedelta(seconds=scan_interval))
+
+ return True
+
+
+class MercedesMeHub(object):
+ """Representation of a base MercedesMe device."""
+
+ def __init__(self, data):
+ """Initialize the entity."""
+ self.data = data
+
+
+class MercedesMeEntity(Entity):
+ """Entity class for MercedesMe devices."""
+
+ def __init__(self, data, internal_name, sensor_name, vin, unit):
+ """Initialize the MercedesMe entity."""
+ self._car = None
+ self._data = data
+ self._state = False
+ self._name = sensor_name
+ self._internal_name = internal_name
+ self._unit = unit
+ self._vin = vin
+
+ @property
+ def name(self):
+ """Return the name of the sensor."""
+ return self._name
+
+ @asyncio.coroutine
+ def async_added_to_hass(self):
+ """Register callbacks."""
+ async_dispatcher_connect(
+ self.hass, SIGNAL_UPDATE_MERCEDESME, self._update_callback)
+
+ def _update_callback(self):
+ """Callback update method."""
+ # If the method is made a callback this should be changed
+ # to the async version. Check core.callback
+ self.schedule_update_ha_state(True)
+
+ @property
+ def unit_of_measurement(self):
+ """Return the unit of measurement."""
+ return self._unit
diff --git a/homeassistant/components/remote/xiaomi_miio.py b/homeassistant/components/remote/xiaomi_miio.py
old mode 100755
new mode 100644
diff --git a/homeassistant/components/sensor/mercedesme.py b/homeassistant/components/sensor/mercedesme.py
old mode 100755
new mode 100644
index 21a63dd562d..bc368745e40
--- a/homeassistant/components/sensor/mercedesme.py
+++ b/homeassistant/components/sensor/mercedesme.py
@@ -1,83 +1,83 @@
-"""
-Support for Mercedes cars with Mercedes ME.
-
-For more details about this component, please refer to the documentation at
-https://home-assistant.io/components/sensor.mercedesme/
-"""
-import logging
-import datetime
-
-from homeassistant.components.mercedesme import (
- DATA_MME, MercedesMeEntity, SENSORS)
-
-
-DEPENDENCIES = ['mercedesme']
-
-_LOGGER = logging.getLogger(__name__)
-
-
-def setup_platform(hass, config, add_devices, discovery_info=None):
- """Setup the sensor platform."""
- if discovery_info is None:
- return
-
- data = hass.data[DATA_MME].data
-
- if not data.cars:
- return
-
- devices = []
- for car in data.cars:
- for key, value in sorted(SENSORS.items()):
- devices.append(
- MercedesMESensor(data, key, value[0], car["vin"], value[1]))
-
- add_devices(devices, True)
-
-
-class MercedesMESensor(MercedesMeEntity):
- """Representation of a Sensor."""
-
- @property
- def state(self):
- """Return the state of the sensor."""
- return self._state
-
- def update(self):
- """Get the latest data and updates the states."""
- _LOGGER.debug("Updating %s", self._internal_name)
-
- self._car = next(
- car for car in self._data.cars if car["vin"] == self._vin)
-
- if self._internal_name == "latestTrip":
- self._state = self._car["latestTrip"]["id"]
- else:
- self._state = self._car[self._internal_name]
-
- @property
- def device_state_attributes(self):
- """Return the state attributes."""
- if self._internal_name == "latestTrip":
- return {
- "duration_seconds":
- self._car["latestTrip"]["durationSeconds"],
- "distance_traveled_km":
- self._car["latestTrip"]["distanceTraveledKm"],
- "started_at": datetime.datetime.fromtimestamp(
- self._car["latestTrip"]["startedAt"]
- ).strftime('%Y-%m-%d %H:%M:%S'),
- "average_speed_km_per_hr":
- self._car["latestTrip"]["averageSpeedKmPerHr"],
- "finished": self._car["latestTrip"]["finished"],
- "last_update": datetime.datetime.fromtimestamp(
- self._car["lastUpdate"]
- ).strftime('%Y-%m-%d %H:%M:%S'),
- "car": self._car["license"]
- }
-
- return {
- "last_update": datetime.datetime.fromtimestamp(
- self._car["lastUpdate"]).strftime('%Y-%m-%d %H:%M:%S'),
- "car": self._car["license"]
- }
+"""
+Support for Mercedes cars with Mercedes ME.
+
+For more details about this component, please refer to the documentation at
+https://home-assistant.io/components/sensor.mercedesme/
+"""
+import logging
+import datetime
+
+from homeassistant.components.mercedesme import (
+ DATA_MME, MercedesMeEntity, SENSORS)
+
+
+DEPENDENCIES = ['mercedesme']
+
+_LOGGER = logging.getLogger(__name__)
+
+
+def setup_platform(hass, config, add_devices, discovery_info=None):
+ """Setup the sensor platform."""
+ if discovery_info is None:
+ return
+
+ data = hass.data[DATA_MME].data
+
+ if not data.cars:
+ return
+
+ devices = []
+ for car in data.cars:
+ for key, value in sorted(SENSORS.items()):
+ devices.append(
+ MercedesMESensor(data, key, value[0], car["vin"], value[1]))
+
+ add_devices(devices, True)
+
+
+class MercedesMESensor(MercedesMeEntity):
+ """Representation of a Sensor."""
+
+ @property
+ def state(self):
+ """Return the state of the sensor."""
+ return self._state
+
+ def update(self):
+ """Get the latest data and updates the states."""
+ _LOGGER.debug("Updating %s", self._internal_name)
+
+ self._car = next(
+ car for car in self._data.cars if car["vin"] == self._vin)
+
+ if self._internal_name == "latestTrip":
+ self._state = self._car["latestTrip"]["id"]
+ else:
+ self._state = self._car[self._internal_name]
+
+ @property
+ def device_state_attributes(self):
+ """Return the state attributes."""
+ if self._internal_name == "latestTrip":
+ return {
+ "duration_seconds":
+ self._car["latestTrip"]["durationSeconds"],
+ "distance_traveled_km":
+ self._car["latestTrip"]["distanceTraveledKm"],
+ "started_at": datetime.datetime.fromtimestamp(
+ self._car["latestTrip"]["startedAt"]
+ ).strftime('%Y-%m-%d %H:%M:%S'),
+ "average_speed_km_per_hr":
+ self._car["latestTrip"]["averageSpeedKmPerHr"],
+ "finished": self._car["latestTrip"]["finished"],
+ "last_update": datetime.datetime.fromtimestamp(
+ self._car["lastUpdate"]
+ ).strftime('%Y-%m-%d %H:%M:%S'),
+ "car": self._car["license"]
+ }
+
+ return {
+ "last_update": datetime.datetime.fromtimestamp(
+ self._car["lastUpdate"]).strftime('%Y-%m-%d %H:%M:%S'),
+ "car": self._car["license"]
+ }
diff --git a/tests/components/calendar/test_google.py b/tests/components/calendar/test_google.py
index 1de825efd99..62c8ea8854f 100644
--- a/tests/components/calendar/test_google.py
+++ b/tests/components/calendar/test_google.py
@@ -1,423 +1,423 @@
-"""The tests for the google calendar component."""
-# pylint: disable=protected-access
-import logging
-import unittest
-from unittest.mock import patch
-
-import pytest
-
-import homeassistant.components.calendar as calendar_base
-import homeassistant.components.calendar.google as calendar
-import homeassistant.util.dt as dt_util
-from homeassistant.const import CONF_PLATFORM, STATE_OFF, STATE_ON
-from homeassistant.helpers.template import DATE_STR_FORMAT
-from tests.common import get_test_home_assistant
-
-TEST_PLATFORM = {calendar_base.DOMAIN: {CONF_PLATFORM: 'test'}}
-
-_LOGGER = logging.getLogger(__name__)
-
-
-class TestComponentsGoogleCalendar(unittest.TestCase):
- """Test the Google calendar."""
-
- hass = None # HomeAssistant
-
- # pylint: disable=invalid-name
- def setUp(self):
- """Setup things to be run when tests are started."""
- self.hass = get_test_home_assistant()
-
- # Set our timezone to CST/Regina so we can check calculations
- # This keeps UTC-6 all year round
- dt_util.set_default_time_zone(dt_util.get_time_zone('America/Regina'))
-
- # pylint: disable=invalid-name
- def tearDown(self):
- """Stop everything that was started."""
- dt_util.set_default_time_zone(dt_util.get_time_zone('UTC'))
-
- self.hass.stop()
-
- @patch('homeassistant.components.calendar.google.GoogleCalendarData')
- def test_all_day_event(self, mock_next_event):
- """Test that we can create an event trigger on device."""
- week_from_today = dt_util.dt.date.today() \
- + dt_util.dt.timedelta(days=7)
- event = {
- 'summary': 'Test All Day Event',
- 'start': {
- 'date': week_from_today.isoformat()
- },
- 'end': {
- 'date': (week_from_today + dt_util.dt.timedelta(days=1))
- .isoformat()
- },
- 'location': 'Test Cases',
- 'description': 'We\'re just testing that all day events get setup '
- 'correctly',
- 'kind': 'calendar#event',
- 'created': '2016-06-23T16:37:57.000Z',
- 'transparency': 'transparent',
- 'updated': '2016-06-24T01:57:21.045Z',
- 'reminders': {'useDefault': True},
- 'organizer': {
- 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
- 'displayName': 'Organizer Name',
- 'self': True
- },
- 'sequence': 0,
- 'creator': {
- 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
- 'displayName': 'Organizer Name',
- 'self': True
- },
- 'id': '_c8rinwq863h45qnucyoi43ny8',
- 'etag': '"2933466882090000"',
- 'htmlLink': 'https://www.google.com/calendar/event?eid=*******',
- 'iCalUID': 'cydrevtfuybguinhomj@google.com',
- 'status': 'confirmed'
- }
-
- mock_next_event.return_value.event = event
-
- device_name = 'Test All Day'
-
- cal = calendar.GoogleCalendarEventDevice(self.hass, None,
- '', {'name': device_name})
-
- self.assertEqual(cal.name, device_name)
-
- self.assertEqual(cal.state, STATE_OFF)
-
- self.assertFalse(cal.offset_reached())
-
- self.assertEqual(cal.device_state_attributes, {
- 'message': event['summary'],
- 'all_day': True,
- 'offset_reached': False,
- 'start_time': '{} 00:00:00'.format(event['start']['date']),
- 'end_time': '{} 00:00:00'.format(event['end']['date']),
- 'location': event['location'],
- 'description': event['description']
- })
-
- @patch('homeassistant.components.calendar.google.GoogleCalendarData')
- def test_future_event(self, mock_next_event):
- """Test that we can create an event trigger on device."""
- one_hour_from_now = dt_util.now() \
- + dt_util.dt.timedelta(minutes=30)
- event = {
- 'start': {
- 'dateTime': one_hour_from_now.isoformat()
- },
- 'end': {
- 'dateTime': (one_hour_from_now
- + dt_util.dt.timedelta(minutes=60))
- .isoformat()
- },
- 'summary': 'Test Event in 30 minutes',
- 'reminders': {'useDefault': True},
- 'id': 'aioehgni435lihje',
- 'status': 'confirmed',
- 'updated': '2016-11-05T15:52:07.329Z',
- 'organizer': {
- 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
- 'displayName': 'Organizer Name',
- 'self': True,
- },
- 'created': '2016-11-05T15:52:07.000Z',
- 'iCalUID': 'dsfohuygtfvgbhnuju@google.com',
- 'sequence': 0,
- 'creator': {
- 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
- 'displayName': 'Organizer Name',
- },
- 'etag': '"2956722254658000"',
- 'kind': 'calendar#event',
- 'htmlLink': 'https://www.google.com/calendar/event?eid=*******',
- }
- mock_next_event.return_value.event = event
-
- device_name = 'Test Future Event'
- device_id = 'test_future_event'
-
- cal = calendar.GoogleCalendarEventDevice(self.hass, None, device_id,
- {'name': device_name})
-
- self.assertEqual(cal.name, device_name)
-
- self.assertEqual(cal.state, STATE_OFF)
-
- self.assertFalse(cal.offset_reached())
-
- self.assertEqual(cal.device_state_attributes, {
- 'message': event['summary'],
- 'all_day': False,
- 'offset_reached': False,
- 'start_time': one_hour_from_now.strftime(DATE_STR_FORMAT),
- 'end_time':
- (one_hour_from_now + dt_util.dt.timedelta(minutes=60))
- .strftime(DATE_STR_FORMAT),
- 'location': '',
- 'description': ''
- })
-
- @patch('homeassistant.components.calendar.google.GoogleCalendarData')
- def test_in_progress_event(self, mock_next_event):
- """Test that we can create an event trigger on device."""
- middle_of_event = dt_util.now() \
- - dt_util.dt.timedelta(minutes=30)
- event = {
- 'start': {
- 'dateTime': middle_of_event.isoformat()
- },
- 'end': {
- 'dateTime': (middle_of_event + dt_util.dt
- .timedelta(minutes=60))
- .isoformat()
- },
- 'summary': 'Test Event in Progress',
- 'reminders': {'useDefault': True},
- 'id': 'aioehgni435lihje',
- 'status': 'confirmed',
- 'updated': '2016-11-05T15:52:07.329Z',
- 'organizer': {
- 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
- 'displayName': 'Organizer Name',
- 'self': True,
- },
- 'created': '2016-11-05T15:52:07.000Z',
- 'iCalUID': 'dsfohuygtfvgbhnuju@google.com',
- 'sequence': 0,
- 'creator': {
- 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
- 'displayName': 'Organizer Name',
- },
- 'etag': '"2956722254658000"',
- 'kind': 'calendar#event',
- 'htmlLink': 'https://www.google.com/calendar/event?eid=*******',
- }
-
- mock_next_event.return_value.event = event
-
- device_name = 'Test Event in Progress'
- device_id = 'test_event_in_progress'
-
- cal = calendar.GoogleCalendarEventDevice(self.hass, None, device_id,
- {'name': device_name})
-
- self.assertEqual(cal.name, device_name)
-
- self.assertEqual(cal.state, STATE_ON)
-
- self.assertFalse(cal.offset_reached())
-
- self.assertEqual(cal.device_state_attributes, {
- 'message': event['summary'],
- 'all_day': False,
- 'offset_reached': False,
- 'start_time': middle_of_event.strftime(DATE_STR_FORMAT),
- 'end_time':
- (middle_of_event + dt_util.dt.timedelta(minutes=60))
- .strftime(DATE_STR_FORMAT),
- 'location': '',
- 'description': ''
- })
-
- @patch('homeassistant.components.calendar.google.GoogleCalendarData')
- def test_offset_in_progress_event(self, mock_next_event):
- """Test that we can create an event trigger on device."""
- middle_of_event = dt_util.now() \
- + dt_util.dt.timedelta(minutes=14)
- event_summary = 'Test Event in Progress'
- event = {
- 'start': {
- 'dateTime': middle_of_event.isoformat()
- },
- 'end': {
- 'dateTime': (middle_of_event + dt_util.dt
- .timedelta(minutes=60))
- .isoformat()
- },
- 'summary': '{} !!-15'.format(event_summary),
- 'reminders': {'useDefault': True},
- 'id': 'aioehgni435lihje',
- 'status': 'confirmed',
- 'updated': '2016-11-05T15:52:07.329Z',
- 'organizer': {
- 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
- 'displayName': 'Organizer Name',
- 'self': True,
- },
- 'created': '2016-11-05T15:52:07.000Z',
- 'iCalUID': 'dsfohuygtfvgbhnuju@google.com',
- 'sequence': 0,
- 'creator': {
- 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
- 'displayName': 'Organizer Name',
- },
- 'etag': '"2956722254658000"',
- 'kind': 'calendar#event',
- 'htmlLink': 'https://www.google.com/calendar/event?eid=*******',
- }
-
- mock_next_event.return_value.event = event
-
- device_name = 'Test Event in Progress'
- device_id = 'test_event_in_progress'
-
- cal = calendar.GoogleCalendarEventDevice(self.hass, None, device_id,
- {'name': device_name})
-
- self.assertEqual(cal.name, device_name)
-
- self.assertEqual(cal.state, STATE_OFF)
-
- self.assertTrue(cal.offset_reached())
-
- self.assertEqual(cal.device_state_attributes, {
- 'message': event_summary,
- 'all_day': False,
- 'offset_reached': True,
- 'start_time': middle_of_event.strftime(DATE_STR_FORMAT),
- 'end_time':
- (middle_of_event + dt_util.dt.timedelta(minutes=60))
- .strftime(DATE_STR_FORMAT),
- 'location': '',
- 'description': ''
- })
-
- @pytest.mark.skip
- @patch('homeassistant.components.calendar.google.GoogleCalendarData')
- def test_all_day_offset_in_progress_event(self, mock_next_event):
- """Test that we can create an event trigger on device."""
- tomorrow = dt_util.dt.date.today() \
- + dt_util.dt.timedelta(days=1)
-
- event_summary = 'Test All Day Event Offset In Progress'
- event = {
- 'summary': '{} !!-25:0'.format(event_summary),
- 'start': {
- 'date': tomorrow.isoformat()
- },
- 'end': {
- 'date': (tomorrow + dt_util.dt.timedelta(days=1))
- .isoformat()
- },
- 'location': 'Test Cases',
- 'description': 'We\'re just testing that all day events get setup '
- 'correctly',
- 'kind': 'calendar#event',
- 'created': '2016-06-23T16:37:57.000Z',
- 'transparency': 'transparent',
- 'updated': '2016-06-24T01:57:21.045Z',
- 'reminders': {'useDefault': True},
- 'organizer': {
- 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
- 'displayName': 'Organizer Name',
- 'self': True
- },
- 'sequence': 0,
- 'creator': {
- 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
- 'displayName': 'Organizer Name',
- 'self': True
- },
- 'id': '_c8rinwq863h45qnucyoi43ny8',
- 'etag': '"2933466882090000"',
- 'htmlLink': 'https://www.google.com/calendar/event?eid=*******',
- 'iCalUID': 'cydrevtfuybguinhomj@google.com',
- 'status': 'confirmed'
- }
-
- mock_next_event.return_value.event = event
-
- device_name = 'Test All Day Offset In Progress'
- device_id = 'test_all_day_offset_in_progress'
-
- cal = calendar.GoogleCalendarEventDevice(self.hass, None, device_id,
- {'name': device_name})
-
- self.assertEqual(cal.name, device_name)
-
- self.assertEqual(cal.state, STATE_OFF)
-
- self.assertTrue(cal.offset_reached())
-
- self.assertEqual(cal.device_state_attributes, {
- 'message': event_summary,
- 'all_day': True,
- 'offset_reached': True,
- 'start_time': '{} 06:00:00'.format(event['start']['date']),
- 'end_time': '{} 06:00:00'.format(event['end']['date']),
- 'location': event['location'],
- 'description': event['description']
- })
-
- @patch('homeassistant.components.calendar.google.GoogleCalendarData')
- def test_all_day_offset_event(self, mock_next_event):
- """Test that we can create an event trigger on device."""
- tomorrow = dt_util.dt.date.today() \
- + dt_util.dt.timedelta(days=2)
-
- offset_hours = (1 + dt_util.now().hour)
- event_summary = 'Test All Day Event Offset'
- event = {
- 'summary': '{} !!-{}:0'.format(event_summary, offset_hours),
- 'start': {
- 'date': tomorrow.isoformat()
- },
- 'end': {
- 'date': (tomorrow + dt_util.dt.timedelta(days=1))
- .isoformat()
- },
- 'location': 'Test Cases',
- 'description': 'We\'re just testing that all day events get setup '
- 'correctly',
- 'kind': 'calendar#event',
- 'created': '2016-06-23T16:37:57.000Z',
- 'transparency': 'transparent',
- 'updated': '2016-06-24T01:57:21.045Z',
- 'reminders': {'useDefault': True},
- 'organizer': {
- 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
- 'displayName': 'Organizer Name',
- 'self': True
- },
- 'sequence': 0,
- 'creator': {
- 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
- 'displayName': 'Organizer Name',
- 'self': True
- },
- 'id': '_c8rinwq863h45qnucyoi43ny8',
- 'etag': '"2933466882090000"',
- 'htmlLink': 'https://www.google.com/calendar/event?eid=*******',
- 'iCalUID': 'cydrevtfuybguinhomj@google.com',
- 'status': 'confirmed'
- }
-
- mock_next_event.return_value.event = event
-
- device_name = 'Test All Day Offset'
- device_id = 'test_all_day_offset'
-
- cal = calendar.GoogleCalendarEventDevice(self.hass, None, device_id,
- {'name': device_name})
-
- self.assertEqual(cal.name, device_name)
-
- self.assertEqual(cal.state, STATE_OFF)
-
- self.assertFalse(cal.offset_reached())
-
- self.assertEqual(cal.device_state_attributes, {
- 'message': event_summary,
- 'all_day': True,
- 'offset_reached': False,
- 'start_time': '{} 00:00:00'.format(event['start']['date']),
- 'end_time': '{} 00:00:00'.format(event['end']['date']),
- 'location': event['location'],
- 'description': event['description']
- })
+"""The tests for the google calendar component."""
+# pylint: disable=protected-access
+import logging
+import unittest
+from unittest.mock import patch
+
+import pytest
+
+import homeassistant.components.calendar as calendar_base
+import homeassistant.components.calendar.google as calendar
+import homeassistant.util.dt as dt_util
+from homeassistant.const import CONF_PLATFORM, STATE_OFF, STATE_ON
+from homeassistant.helpers.template import DATE_STR_FORMAT
+from tests.common import get_test_home_assistant
+
+TEST_PLATFORM = {calendar_base.DOMAIN: {CONF_PLATFORM: 'test'}}
+
+_LOGGER = logging.getLogger(__name__)
+
+
+class TestComponentsGoogleCalendar(unittest.TestCase):
+ """Test the Google calendar."""
+
+ hass = None # HomeAssistant
+
+ # pylint: disable=invalid-name
+ def setUp(self):
+ """Setup things to be run when tests are started."""
+ self.hass = get_test_home_assistant()
+
+ # Set our timezone to CST/Regina so we can check calculations
+ # This keeps UTC-6 all year round
+ dt_util.set_default_time_zone(dt_util.get_time_zone('America/Regina'))
+
+ # pylint: disable=invalid-name
+ def tearDown(self):
+ """Stop everything that was started."""
+ dt_util.set_default_time_zone(dt_util.get_time_zone('UTC'))
+
+ self.hass.stop()
+
+ @patch('homeassistant.components.calendar.google.GoogleCalendarData')
+ def test_all_day_event(self, mock_next_event):
+ """Test that we can create an event trigger on device."""
+ week_from_today = dt_util.dt.date.today() \
+ + dt_util.dt.timedelta(days=7)
+ event = {
+ 'summary': 'Test All Day Event',
+ 'start': {
+ 'date': week_from_today.isoformat()
+ },
+ 'end': {
+ 'date': (week_from_today + dt_util.dt.timedelta(days=1))
+ .isoformat()
+ },
+ 'location': 'Test Cases',
+ 'description': 'We\'re just testing that all day events get setup '
+ 'correctly',
+ 'kind': 'calendar#event',
+ 'created': '2016-06-23T16:37:57.000Z',
+ 'transparency': 'transparent',
+ 'updated': '2016-06-24T01:57:21.045Z',
+ 'reminders': {'useDefault': True},
+ 'organizer': {
+ 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
+ 'displayName': 'Organizer Name',
+ 'self': True
+ },
+ 'sequence': 0,
+ 'creator': {
+ 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
+ 'displayName': 'Organizer Name',
+ 'self': True
+ },
+ 'id': '_c8rinwq863h45qnucyoi43ny8',
+ 'etag': '"2933466882090000"',
+ 'htmlLink': 'https://www.google.com/calendar/event?eid=*******',
+ 'iCalUID': 'cydrevtfuybguinhomj@google.com',
+ 'status': 'confirmed'
+ }
+
+ mock_next_event.return_value.event = event
+
+ device_name = 'Test All Day'
+
+ cal = calendar.GoogleCalendarEventDevice(self.hass, None,
+ '', {'name': device_name})
+
+ self.assertEqual(cal.name, device_name)
+
+ self.assertEqual(cal.state, STATE_OFF)
+
+ self.assertFalse(cal.offset_reached())
+
+ self.assertEqual(cal.device_state_attributes, {
+ 'message': event['summary'],
+ 'all_day': True,
+ 'offset_reached': False,
+ 'start_time': '{} 00:00:00'.format(event['start']['date']),
+ 'end_time': '{} 00:00:00'.format(event['end']['date']),
+ 'location': event['location'],
+ 'description': event['description']
+ })
+
+ @patch('homeassistant.components.calendar.google.GoogleCalendarData')
+ def test_future_event(self, mock_next_event):
+ """Test that we can create an event trigger on device."""
+ one_hour_from_now = dt_util.now() \
+ + dt_util.dt.timedelta(minutes=30)
+ event = {
+ 'start': {
+ 'dateTime': one_hour_from_now.isoformat()
+ },
+ 'end': {
+ 'dateTime': (one_hour_from_now
+ + dt_util.dt.timedelta(minutes=60))
+ .isoformat()
+ },
+ 'summary': 'Test Event in 30 minutes',
+ 'reminders': {'useDefault': True},
+ 'id': 'aioehgni435lihje',
+ 'status': 'confirmed',
+ 'updated': '2016-11-05T15:52:07.329Z',
+ 'organizer': {
+ 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
+ 'displayName': 'Organizer Name',
+ 'self': True,
+ },
+ 'created': '2016-11-05T15:52:07.000Z',
+ 'iCalUID': 'dsfohuygtfvgbhnuju@google.com',
+ 'sequence': 0,
+ 'creator': {
+ 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
+ 'displayName': 'Organizer Name',
+ },
+ 'etag': '"2956722254658000"',
+ 'kind': 'calendar#event',
+ 'htmlLink': 'https://www.google.com/calendar/event?eid=*******',
+ }
+ mock_next_event.return_value.event = event
+
+ device_name = 'Test Future Event'
+ device_id = 'test_future_event'
+
+ cal = calendar.GoogleCalendarEventDevice(self.hass, None, device_id,
+ {'name': device_name})
+
+ self.assertEqual(cal.name, device_name)
+
+ self.assertEqual(cal.state, STATE_OFF)
+
+ self.assertFalse(cal.offset_reached())
+
+ self.assertEqual(cal.device_state_attributes, {
+ 'message': event['summary'],
+ 'all_day': False,
+ 'offset_reached': False,
+ 'start_time': one_hour_from_now.strftime(DATE_STR_FORMAT),
+ 'end_time':
+ (one_hour_from_now + dt_util.dt.timedelta(minutes=60))
+ .strftime(DATE_STR_FORMAT),
+ 'location': '',
+ 'description': ''
+ })
+
+ @patch('homeassistant.components.calendar.google.GoogleCalendarData')
+ def test_in_progress_event(self, mock_next_event):
+ """Test that we can create an event trigger on device."""
+ middle_of_event = dt_util.now() \
+ - dt_util.dt.timedelta(minutes=30)
+ event = {
+ 'start': {
+ 'dateTime': middle_of_event.isoformat()
+ },
+ 'end': {
+ 'dateTime': (middle_of_event + dt_util.dt
+ .timedelta(minutes=60))
+ .isoformat()
+ },
+ 'summary': 'Test Event in Progress',
+ 'reminders': {'useDefault': True},
+ 'id': 'aioehgni435lihje',
+ 'status': 'confirmed',
+ 'updated': '2016-11-05T15:52:07.329Z',
+ 'organizer': {
+ 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
+ 'displayName': 'Organizer Name',
+ 'self': True,
+ },
+ 'created': '2016-11-05T15:52:07.000Z',
+ 'iCalUID': 'dsfohuygtfvgbhnuju@google.com',
+ 'sequence': 0,
+ 'creator': {
+ 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
+ 'displayName': 'Organizer Name',
+ },
+ 'etag': '"2956722254658000"',
+ 'kind': 'calendar#event',
+ 'htmlLink': 'https://www.google.com/calendar/event?eid=*******',
+ }
+
+ mock_next_event.return_value.event = event
+
+ device_name = 'Test Event in Progress'
+ device_id = 'test_event_in_progress'
+
+ cal = calendar.GoogleCalendarEventDevice(self.hass, None, device_id,
+ {'name': device_name})
+
+ self.assertEqual(cal.name, device_name)
+
+ self.assertEqual(cal.state, STATE_ON)
+
+ self.assertFalse(cal.offset_reached())
+
+ self.assertEqual(cal.device_state_attributes, {
+ 'message': event['summary'],
+ 'all_day': False,
+ 'offset_reached': False,
+ 'start_time': middle_of_event.strftime(DATE_STR_FORMAT),
+ 'end_time':
+ (middle_of_event + dt_util.dt.timedelta(minutes=60))
+ .strftime(DATE_STR_FORMAT),
+ 'location': '',
+ 'description': ''
+ })
+
+ @patch('homeassistant.components.calendar.google.GoogleCalendarData')
+ def test_offset_in_progress_event(self, mock_next_event):
+ """Test that we can create an event trigger on device."""
+ middle_of_event = dt_util.now() \
+ + dt_util.dt.timedelta(minutes=14)
+ event_summary = 'Test Event in Progress'
+ event = {
+ 'start': {
+ 'dateTime': middle_of_event.isoformat()
+ },
+ 'end': {
+ 'dateTime': (middle_of_event + dt_util.dt
+ .timedelta(minutes=60))
+ .isoformat()
+ },
+ 'summary': '{} !!-15'.format(event_summary),
+ 'reminders': {'useDefault': True},
+ 'id': 'aioehgni435lihje',
+ 'status': 'confirmed',
+ 'updated': '2016-11-05T15:52:07.329Z',
+ 'organizer': {
+ 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
+ 'displayName': 'Organizer Name',
+ 'self': True,
+ },
+ 'created': '2016-11-05T15:52:07.000Z',
+ 'iCalUID': 'dsfohuygtfvgbhnuju@google.com',
+ 'sequence': 0,
+ 'creator': {
+ 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
+ 'displayName': 'Organizer Name',
+ },
+ 'etag': '"2956722254658000"',
+ 'kind': 'calendar#event',
+ 'htmlLink': 'https://www.google.com/calendar/event?eid=*******',
+ }
+
+ mock_next_event.return_value.event = event
+
+ device_name = 'Test Event in Progress'
+ device_id = 'test_event_in_progress'
+
+ cal = calendar.GoogleCalendarEventDevice(self.hass, None, device_id,
+ {'name': device_name})
+
+ self.assertEqual(cal.name, device_name)
+
+ self.assertEqual(cal.state, STATE_OFF)
+
+ self.assertTrue(cal.offset_reached())
+
+ self.assertEqual(cal.device_state_attributes, {
+ 'message': event_summary,
+ 'all_day': False,
+ 'offset_reached': True,
+ 'start_time': middle_of_event.strftime(DATE_STR_FORMAT),
+ 'end_time':
+ (middle_of_event + dt_util.dt.timedelta(minutes=60))
+ .strftime(DATE_STR_FORMAT),
+ 'location': '',
+ 'description': ''
+ })
+
+ @pytest.mark.skip
+ @patch('homeassistant.components.calendar.google.GoogleCalendarData')
+ def test_all_day_offset_in_progress_event(self, mock_next_event):
+ """Test that we can create an event trigger on device."""
+ tomorrow = dt_util.dt.date.today() \
+ + dt_util.dt.timedelta(days=1)
+
+ event_summary = 'Test All Day Event Offset In Progress'
+ event = {
+ 'summary': '{} !!-25:0'.format(event_summary),
+ 'start': {
+ 'date': tomorrow.isoformat()
+ },
+ 'end': {
+ 'date': (tomorrow + dt_util.dt.timedelta(days=1))
+ .isoformat()
+ },
+ 'location': 'Test Cases',
+ 'description': 'We\'re just testing that all day events get setup '
+ 'correctly',
+ 'kind': 'calendar#event',
+ 'created': '2016-06-23T16:37:57.000Z',
+ 'transparency': 'transparent',
+ 'updated': '2016-06-24T01:57:21.045Z',
+ 'reminders': {'useDefault': True},
+ 'organizer': {
+ 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
+ 'displayName': 'Organizer Name',
+ 'self': True
+ },
+ 'sequence': 0,
+ 'creator': {
+ 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
+ 'displayName': 'Organizer Name',
+ 'self': True
+ },
+ 'id': '_c8rinwq863h45qnucyoi43ny8',
+ 'etag': '"2933466882090000"',
+ 'htmlLink': 'https://www.google.com/calendar/event?eid=*******',
+ 'iCalUID': 'cydrevtfuybguinhomj@google.com',
+ 'status': 'confirmed'
+ }
+
+ mock_next_event.return_value.event = event
+
+ device_name = 'Test All Day Offset In Progress'
+ device_id = 'test_all_day_offset_in_progress'
+
+ cal = calendar.GoogleCalendarEventDevice(self.hass, None, device_id,
+ {'name': device_name})
+
+ self.assertEqual(cal.name, device_name)
+
+ self.assertEqual(cal.state, STATE_OFF)
+
+ self.assertTrue(cal.offset_reached())
+
+ self.assertEqual(cal.device_state_attributes, {
+ 'message': event_summary,
+ 'all_day': True,
+ 'offset_reached': True,
+ 'start_time': '{} 06:00:00'.format(event['start']['date']),
+ 'end_time': '{} 06:00:00'.format(event['end']['date']),
+ 'location': event['location'],
+ 'description': event['description']
+ })
+
+ @patch('homeassistant.components.calendar.google.GoogleCalendarData')
+ def test_all_day_offset_event(self, mock_next_event):
+ """Test that we can create an event trigger on device."""
+ tomorrow = dt_util.dt.date.today() \
+ + dt_util.dt.timedelta(days=2)
+
+ offset_hours = (1 + dt_util.now().hour)
+ event_summary = 'Test All Day Event Offset'
+ event = {
+ 'summary': '{} !!-{}:0'.format(event_summary, offset_hours),
+ 'start': {
+ 'date': tomorrow.isoformat()
+ },
+ 'end': {
+ 'date': (tomorrow + dt_util.dt.timedelta(days=1))
+ .isoformat()
+ },
+ 'location': 'Test Cases',
+ 'description': 'We\'re just testing that all day events get setup '
+ 'correctly',
+ 'kind': 'calendar#event',
+ 'created': '2016-06-23T16:37:57.000Z',
+ 'transparency': 'transparent',
+ 'updated': '2016-06-24T01:57:21.045Z',
+ 'reminders': {'useDefault': True},
+ 'organizer': {
+ 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
+ 'displayName': 'Organizer Name',
+ 'self': True
+ },
+ 'sequence': 0,
+ 'creator': {
+ 'email': 'uvrttabwegnui4gtia3vyqb@import.calendar.google.com',
+ 'displayName': 'Organizer Name',
+ 'self': True
+ },
+ 'id': '_c8rinwq863h45qnucyoi43ny8',
+ 'etag': '"2933466882090000"',
+ 'htmlLink': 'https://www.google.com/calendar/event?eid=*******',
+ 'iCalUID': 'cydrevtfuybguinhomj@google.com',
+ 'status': 'confirmed'
+ }
+
+ mock_next_event.return_value.event = event
+
+ device_name = 'Test All Day Offset'
+ device_id = 'test_all_day_offset'
+
+ cal = calendar.GoogleCalendarEventDevice(self.hass, None, device_id,
+ {'name': device_name})
+
+ self.assertEqual(cal.name, device_name)
+
+ self.assertEqual(cal.state, STATE_OFF)
+
+ self.assertFalse(cal.offset_reached())
+
+ self.assertEqual(cal.device_state_attributes, {
+ 'message': event_summary,
+ 'all_day': True,
+ 'offset_reached': False,
+ 'start_time': '{} 00:00:00'.format(event['start']['date']),
+ 'end_time': '{} 00:00:00'.format(event['end']['date']),
+ 'location': event['location'],
+ 'description': event['description']
+ })
diff --git a/tests/components/cloud/__init__.py b/tests/components/cloud/__init__.py
index 707e49f670f..7a4e9f2950e 100644
--- a/tests/components/cloud/__init__.py
+++ b/tests/components/cloud/__init__.py
@@ -1 +1 @@
-"""Tests for the cloud component."""
+"""Tests for the cloud component."""
diff --git a/tests/components/device_tracker/test_xiaomi.py b/tests/components/device_tracker/test_xiaomi.py
index 94a4566a17b..19f25b514db 100644
--- a/tests/components/device_tracker/test_xiaomi.py
+++ b/tests/components/device_tracker/test_xiaomi.py
@@ -1,265 +1,265 @@
-"""The tests for the Xiaomi router device tracker platform."""
-import logging
-import unittest
-from unittest import mock
-from unittest.mock import patch
-
-import requests
-
-from homeassistant.components.device_tracker import DOMAIN, xiaomi as xiaomi
-from homeassistant.components.device_tracker.xiaomi import get_scanner
-from homeassistant.const import (CONF_HOST, CONF_USERNAME, CONF_PASSWORD,
- CONF_PLATFORM)
-from tests.common import get_test_home_assistant
-
-_LOGGER = logging.getLogger(__name__)
-
-INVALID_USERNAME = 'bob'
-TOKEN_TIMEOUT_USERNAME = 'tok'
-URL_AUTHORIZE = 'http://192.168.0.1/cgi-bin/luci/api/xqsystem/login'
-URL_LIST_END = 'api/misystem/devicelist'
-
-FIRST_CALL = True
-
-
-def mocked_requests(*args, **kwargs):
- """Mock requests.get invocations."""
- class MockResponse:
- """Class to represent a mocked response."""
-
- def __init__(self, json_data, status_code):
- """Initialize the mock response class."""
- self.json_data = json_data
- self.status_code = status_code
-
- def json(self):
- """Return the json of the response."""
- return self.json_data
-
- @property
- def content(self):
- """Return the content of the response."""
- return self.json()
-
- def raise_for_status(self):
- """Raise an HTTPError if status is not 200."""
- if self.status_code != 200:
- raise requests.HTTPError(self.status_code)
-
- data = kwargs.get('data')
- global FIRST_CALL
-
- if data and data.get('username', None) == INVALID_USERNAME:
- # deliver an invalid token
- return MockResponse({
- "code": "401",
- "msg": "Invalid token"
- }, 200)
- elif data and data.get('username', None) == TOKEN_TIMEOUT_USERNAME:
- # deliver an expired token
- return MockResponse({
- "url": "/cgi-bin/luci/;stok=ef5860/web/home",
- "token": "timedOut",
- "code": "0"
- }, 200)
- elif str(args[0]).startswith(URL_AUTHORIZE):
- # deliver an authorized token
- return MockResponse({
- "url": "/cgi-bin/luci/;stok=ef5860/web/home",
- "token": "ef5860",
- "code": "0"
- }, 200)
- elif str(args[0]).endswith("timedOut/" + URL_LIST_END) \
- and FIRST_CALL is True:
- FIRST_CALL = False
- # deliver an error when called with expired token
- return MockResponse({
- "code": "401",
- "msg": "Invalid token"
- }, 200)
- elif str(args[0]).endswith(URL_LIST_END):
- # deliver the device list
- return MockResponse({
- "mac": "1C:98:EC:0E:D5:A4",
- "list": [
- {
- "mac": "23:83:BF:F6:38:A0",
- "oname": "12255ff",
- "isap": 0,
- "parent": "",
- "authority": {
- "wan": 1,
- "pridisk": 0,
- "admin": 1,
- "lan": 0
- },
- "push": 0,
- "online": 1,
- "name": "Device1",
- "times": 0,
- "ip": [
- {
- "downspeed": "0",
- "online": "496957",
- "active": 1,
- "upspeed": "0",
- "ip": "192.168.0.25"
- }
- ],
- "statistics": {
- "downspeed": "0",
- "online": "496957",
- "upspeed": "0"
- },
- "icon": "",
- "type": 1
- },
- {
- "mac": "1D:98:EC:5E:D5:A6",
- "oname": "CdddFG58",
- "isap": 0,
- "parent": "",
- "authority": {
- "wan": 1,
- "pridisk": 0,
- "admin": 1,
- "lan": 0
- },
- "push": 0,
- "online": 1,
- "name": "Device2",
- "times": 0,
- "ip": [
- {
- "downspeed": "0",
- "online": "347325",
- "active": 1,
- "upspeed": "0",
- "ip": "192.168.0.3"
- }
- ],
- "statistics": {
- "downspeed": "0",
- "online": "347325",
- "upspeed": "0"
- },
- "icon": "",
- "type": 0
- },
- ],
- "code": 0
- }, 200)
- else:
- _LOGGER.debug('UNKNOWN ROUTE')
-
-
-class TestXiaomiDeviceScanner(unittest.TestCase):
- """Xiaomi device scanner test class."""
-
- def setUp(self):
- """Initialize values for this testcase class."""
- self.hass = get_test_home_assistant()
-
- def tearDown(self):
- """Stop everything that was started."""
- self.hass.stop()
-
- @mock.patch(
- 'homeassistant.components.device_tracker.xiaomi.XiaomiDeviceScanner',
- return_value=mock.MagicMock())
- def test_config(self, xiaomi_mock):
- """Testing minimal configuration."""
- config = {
- DOMAIN: xiaomi.PLATFORM_SCHEMA({
- CONF_PLATFORM: xiaomi.DOMAIN,
- CONF_HOST: '192.168.0.1',
- CONF_PASSWORD: 'passwordTest'
- })
- }
- xiaomi.get_scanner(self.hass, config)
- self.assertEqual(xiaomi_mock.call_count, 1)
- self.assertEqual(xiaomi_mock.call_args, mock.call(config[DOMAIN]))
- call_arg = xiaomi_mock.call_args[0][0]
- self.assertEqual(call_arg['username'], 'admin')
- self.assertEqual(call_arg['password'], 'passwordTest')
- self.assertEqual(call_arg['host'], '192.168.0.1')
- self.assertEqual(call_arg['platform'], 'device_tracker')
-
- @mock.patch(
- 'homeassistant.components.device_tracker.xiaomi.XiaomiDeviceScanner',
- return_value=mock.MagicMock())
- def test_config_full(self, xiaomi_mock):
- """Testing full configuration."""
- config = {
- DOMAIN: xiaomi.PLATFORM_SCHEMA({
- CONF_PLATFORM: xiaomi.DOMAIN,
- CONF_HOST: '192.168.0.1',
- CONF_USERNAME: 'alternativeAdminName',
- CONF_PASSWORD: 'passwordTest'
- })
- }
- xiaomi.get_scanner(self.hass, config)
- self.assertEqual(xiaomi_mock.call_count, 1)
- self.assertEqual(xiaomi_mock.call_args, mock.call(config[DOMAIN]))
- call_arg = xiaomi_mock.call_args[0][0]
- self.assertEqual(call_arg['username'], 'alternativeAdminName')
- self.assertEqual(call_arg['password'], 'passwordTest')
- self.assertEqual(call_arg['host'], '192.168.0.1')
- self.assertEqual(call_arg['platform'], 'device_tracker')
-
- @patch('requests.get', side_effect=mocked_requests)
- @patch('requests.post', side_effect=mocked_requests)
- def test_invalid_credential(self, mock_get, mock_post):
- """"Testing invalid credential handling."""
- config = {
- DOMAIN: xiaomi.PLATFORM_SCHEMA({
- CONF_PLATFORM: xiaomi.DOMAIN,
- CONF_HOST: '192.168.0.1',
- CONF_USERNAME: INVALID_USERNAME,
- CONF_PASSWORD: 'passwordTest'
- })
- }
- self.assertIsNone(get_scanner(self.hass, config))
-
- @patch('requests.get', side_effect=mocked_requests)
- @patch('requests.post', side_effect=mocked_requests)
- def test_valid_credential(self, mock_get, mock_post):
- """"Testing valid refresh."""
- config = {
- DOMAIN: xiaomi.PLATFORM_SCHEMA({
- CONF_PLATFORM: xiaomi.DOMAIN,
- CONF_HOST: '192.168.0.1',
- CONF_USERNAME: 'admin',
- CONF_PASSWORD: 'passwordTest'
- })
- }
- scanner = get_scanner(self.hass, config)
- self.assertIsNotNone(scanner)
- self.assertEqual(2, len(scanner.scan_devices()))
- self.assertEqual("Device1",
- scanner.get_device_name("23:83:BF:F6:38:A0"))
- self.assertEqual("Device2",
- scanner.get_device_name("1D:98:EC:5E:D5:A6"))
-
- @patch('requests.get', side_effect=mocked_requests)
- @patch('requests.post', side_effect=mocked_requests)
- def test_token_timed_out(self, mock_get, mock_post):
- """"Testing refresh with a timed out token.
-
- New token is requested and list is downloaded a second time.
- """
- config = {
- DOMAIN: xiaomi.PLATFORM_SCHEMA({
- CONF_PLATFORM: xiaomi.DOMAIN,
- CONF_HOST: '192.168.0.1',
- CONF_USERNAME: TOKEN_TIMEOUT_USERNAME,
- CONF_PASSWORD: 'passwordTest'
- })
- }
- scanner = get_scanner(self.hass, config)
- self.assertIsNotNone(scanner)
- self.assertEqual(2, len(scanner.scan_devices()))
- self.assertEqual("Device1",
- scanner.get_device_name("23:83:BF:F6:38:A0"))
- self.assertEqual("Device2",
- scanner.get_device_name("1D:98:EC:5E:D5:A6"))
+"""The tests for the Xiaomi router device tracker platform."""
+import logging
+import unittest
+from unittest import mock
+from unittest.mock import patch
+
+import requests
+
+from homeassistant.components.device_tracker import DOMAIN, xiaomi as xiaomi
+from homeassistant.components.device_tracker.xiaomi import get_scanner
+from homeassistant.const import (CONF_HOST, CONF_USERNAME, CONF_PASSWORD,
+ CONF_PLATFORM)
+from tests.common import get_test_home_assistant
+
+_LOGGER = logging.getLogger(__name__)
+
+INVALID_USERNAME = 'bob'
+TOKEN_TIMEOUT_USERNAME = 'tok'
+URL_AUTHORIZE = 'http://192.168.0.1/cgi-bin/luci/api/xqsystem/login'
+URL_LIST_END = 'api/misystem/devicelist'
+
+FIRST_CALL = True
+
+
+def mocked_requests(*args, **kwargs):
+ """Mock requests.get invocations."""
+ class MockResponse:
+ """Class to represent a mocked response."""
+
+ def __init__(self, json_data, status_code):
+ """Initialize the mock response class."""
+ self.json_data = json_data
+ self.status_code = status_code
+
+ def json(self):
+ """Return the json of the response."""
+ return self.json_data
+
+ @property
+ def content(self):
+ """Return the content of the response."""
+ return self.json()
+
+ def raise_for_status(self):
+ """Raise an HTTPError if status is not 200."""
+ if self.status_code != 200:
+ raise requests.HTTPError(self.status_code)
+
+ data = kwargs.get('data')
+ global FIRST_CALL
+
+ if data and data.get('username', None) == INVALID_USERNAME:
+ # deliver an invalid token
+ return MockResponse({
+ "code": "401",
+ "msg": "Invalid token"
+ }, 200)
+ elif data and data.get('username', None) == TOKEN_TIMEOUT_USERNAME:
+ # deliver an expired token
+ return MockResponse({
+ "url": "/cgi-bin/luci/;stok=ef5860/web/home",
+ "token": "timedOut",
+ "code": "0"
+ }, 200)
+ elif str(args[0]).startswith(URL_AUTHORIZE):
+ # deliver an authorized token
+ return MockResponse({
+ "url": "/cgi-bin/luci/;stok=ef5860/web/home",
+ "token": "ef5860",
+ "code": "0"
+ }, 200)
+ elif str(args[0]).endswith("timedOut/" + URL_LIST_END) \
+ and FIRST_CALL is True:
+ FIRST_CALL = False
+ # deliver an error when called with expired token
+ return MockResponse({
+ "code": "401",
+ "msg": "Invalid token"
+ }, 200)
+ elif str(args[0]).endswith(URL_LIST_END):
+ # deliver the device list
+ return MockResponse({
+ "mac": "1C:98:EC:0E:D5:A4",
+ "list": [
+ {
+ "mac": "23:83:BF:F6:38:A0",
+ "oname": "12255ff",
+ "isap": 0,
+ "parent": "",
+ "authority": {
+ "wan": 1,
+ "pridisk": 0,
+ "admin": 1,
+ "lan": 0
+ },
+ "push": 0,
+ "online": 1,
+ "name": "Device1",
+ "times": 0,
+ "ip": [
+ {
+ "downspeed": "0",
+ "online": "496957",
+ "active": 1,
+ "upspeed": "0",
+ "ip": "192.168.0.25"
+ }
+ ],
+ "statistics": {
+ "downspeed": "0",
+ "online": "496957",
+ "upspeed": "0"
+ },
+ "icon": "",
+ "type": 1
+ },
+ {
+ "mac": "1D:98:EC:5E:D5:A6",
+ "oname": "CdddFG58",
+ "isap": 0,
+ "parent": "",
+ "authority": {
+ "wan": 1,
+ "pridisk": 0,
+ "admin": 1,
+ "lan": 0
+ },
+ "push": 0,
+ "online": 1,
+ "name": "Device2",
+ "times": 0,
+ "ip": [
+ {
+ "downspeed": "0",
+ "online": "347325",
+ "active": 1,
+ "upspeed": "0",
+ "ip": "192.168.0.3"
+ }
+ ],
+ "statistics": {
+ "downspeed": "0",
+ "online": "347325",
+ "upspeed": "0"
+ },
+ "icon": "",
+ "type": 0
+ },
+ ],
+ "code": 0
+ }, 200)
+ else:
+ _LOGGER.debug('UNKNOWN ROUTE')
+
+
+class TestXiaomiDeviceScanner(unittest.TestCase):
+ """Xiaomi device scanner test class."""
+
+ def setUp(self):
+ """Initialize values for this testcase class."""
+ self.hass = get_test_home_assistant()
+
+ def tearDown(self):
+ """Stop everything that was started."""
+ self.hass.stop()
+
+ @mock.patch(
+ 'homeassistant.components.device_tracker.xiaomi.XiaomiDeviceScanner',
+ return_value=mock.MagicMock())
+ def test_config(self, xiaomi_mock):
+ """Testing minimal configuration."""
+ config = {
+ DOMAIN: xiaomi.PLATFORM_SCHEMA({
+ CONF_PLATFORM: xiaomi.DOMAIN,
+ CONF_HOST: '192.168.0.1',
+ CONF_PASSWORD: 'passwordTest'
+ })
+ }
+ xiaomi.get_scanner(self.hass, config)
+ self.assertEqual(xiaomi_mock.call_count, 1)
+ self.assertEqual(xiaomi_mock.call_args, mock.call(config[DOMAIN]))
+ call_arg = xiaomi_mock.call_args[0][0]
+ self.assertEqual(call_arg['username'], 'admin')
+ self.assertEqual(call_arg['password'], 'passwordTest')
+ self.assertEqual(call_arg['host'], '192.168.0.1')
+ self.assertEqual(call_arg['platform'], 'device_tracker')
+
+ @mock.patch(
+ 'homeassistant.components.device_tracker.xiaomi.XiaomiDeviceScanner',
+ return_value=mock.MagicMock())
+ def test_config_full(self, xiaomi_mock):
+ """Testing full configuration."""
+ config = {
+ DOMAIN: xiaomi.PLATFORM_SCHEMA({
+ CONF_PLATFORM: xiaomi.DOMAIN,
+ CONF_HOST: '192.168.0.1',
+ CONF_USERNAME: 'alternativeAdminName',
+ CONF_PASSWORD: 'passwordTest'
+ })
+ }
+ xiaomi.get_scanner(self.hass, config)
+ self.assertEqual(xiaomi_mock.call_count, 1)
+ self.assertEqual(xiaomi_mock.call_args, mock.call(config[DOMAIN]))
+ call_arg = xiaomi_mock.call_args[0][0]
+ self.assertEqual(call_arg['username'], 'alternativeAdminName')
+ self.assertEqual(call_arg['password'], 'passwordTest')
+ self.assertEqual(call_arg['host'], '192.168.0.1')
+ self.assertEqual(call_arg['platform'], 'device_tracker')
+
+ @patch('requests.get', side_effect=mocked_requests)
+ @patch('requests.post', side_effect=mocked_requests)
+ def test_invalid_credential(self, mock_get, mock_post):
+ """"Testing invalid credential handling."""
+ config = {
+ DOMAIN: xiaomi.PLATFORM_SCHEMA({
+ CONF_PLATFORM: xiaomi.DOMAIN,
+ CONF_HOST: '192.168.0.1',
+ CONF_USERNAME: INVALID_USERNAME,
+ CONF_PASSWORD: 'passwordTest'
+ })
+ }
+ self.assertIsNone(get_scanner(self.hass, config))
+
+ @patch('requests.get', side_effect=mocked_requests)
+ @patch('requests.post', side_effect=mocked_requests)
+ def test_valid_credential(self, mock_get, mock_post):
+ """"Testing valid refresh."""
+ config = {
+ DOMAIN: xiaomi.PLATFORM_SCHEMA({
+ CONF_PLATFORM: xiaomi.DOMAIN,
+ CONF_HOST: '192.168.0.1',
+ CONF_USERNAME: 'admin',
+ CONF_PASSWORD: 'passwordTest'
+ })
+ }
+ scanner = get_scanner(self.hass, config)
+ self.assertIsNotNone(scanner)
+ self.assertEqual(2, len(scanner.scan_devices()))
+ self.assertEqual("Device1",
+ scanner.get_device_name("23:83:BF:F6:38:A0"))
+ self.assertEqual("Device2",
+ scanner.get_device_name("1D:98:EC:5E:D5:A6"))
+
+ @patch('requests.get', side_effect=mocked_requests)
+ @patch('requests.post', side_effect=mocked_requests)
+ def test_token_timed_out(self, mock_get, mock_post):
+ """"Testing refresh with a timed out token.
+
+ New token is requested and list is downloaded a second time.
+ """
+ config = {
+ DOMAIN: xiaomi.PLATFORM_SCHEMA({
+ CONF_PLATFORM: xiaomi.DOMAIN,
+ CONF_HOST: '192.168.0.1',
+ CONF_USERNAME: TOKEN_TIMEOUT_USERNAME,
+ CONF_PASSWORD: 'passwordTest'
+ })
+ }
+ scanner = get_scanner(self.hass, config)
+ self.assertIsNotNone(scanner)
+ self.assertEqual(2, len(scanner.scan_devices()))
+ self.assertEqual("Device1",
+ scanner.get_device_name("23:83:BF:F6:38:A0"))
+ self.assertEqual("Device2",
+ scanner.get_device_name("1D:98:EC:5E:D5:A6"))
diff --git a/tests/components/emulated_hue/test_init.py b/tests/components/emulated_hue/test_init.py
index 25bcbc1dd55..06613f1336a 100644
--- a/tests/components/emulated_hue/test_init.py
+++ b/tests/components/emulated_hue/test_init.py
@@ -1,128 +1,128 @@
-"""Test the Emulated Hue component."""
-import json
-
-from unittest.mock import patch, Mock, mock_open
-
-from homeassistant.components.emulated_hue import Config, _LOGGER
-
-
-def test_config_google_home_entity_id_to_number():
- """Test config adheres to the type."""
- conf = Config(Mock(), {
- 'type': 'google_home'
- })
-
- mop = mock_open(read_data=json.dumps({'1': 'light.test2'}))
- handle = mop()
-
- with patch('homeassistant.util.json.open', mop, create=True):
- number = conf.entity_id_to_number('light.test')
- assert number == '2'
- assert handle.write.call_count == 1
- assert json.loads(handle.write.mock_calls[0][1][0]) == {
- '1': 'light.test2',
- '2': 'light.test',
- }
-
- number = conf.entity_id_to_number('light.test')
- assert number == '2'
- assert handle.write.call_count == 1
-
- number = conf.entity_id_to_number('light.test2')
- assert number == '1'
- assert handle.write.call_count == 1
-
- entity_id = conf.number_to_entity_id('1')
- assert entity_id == 'light.test2'
-
-
-def test_config_google_home_entity_id_to_number_altered():
- """Test config adheres to the type."""
- conf = Config(Mock(), {
- 'type': 'google_home'
- })
-
- mop = mock_open(read_data=json.dumps({'21': 'light.test2'}))
- handle = mop()
-
- with patch('homeassistant.util.json.open', mop, create=True):
- number = conf.entity_id_to_number('light.test')
- assert number == '22'
- assert handle.write.call_count == 1
- assert json.loads(handle.write.mock_calls[0][1][0]) == {
- '21': 'light.test2',
- '22': 'light.test',
- }
-
- number = conf.entity_id_to_number('light.test')
- assert number == '22'
- assert handle.write.call_count == 1
-
- number = conf.entity_id_to_number('light.test2')
- assert number == '21'
- assert handle.write.call_count == 1
-
- entity_id = conf.number_to_entity_id('21')
- assert entity_id == 'light.test2'
-
-
-def test_config_google_home_entity_id_to_number_empty():
- """Test config adheres to the type."""
- conf = Config(Mock(), {
- 'type': 'google_home'
- })
-
- mop = mock_open(read_data='')
- handle = mop()
-
- with patch('homeassistant.util.json.open', mop, create=True):
- number = conf.entity_id_to_number('light.test')
- assert number == '1'
- assert handle.write.call_count == 1
- assert json.loads(handle.write.mock_calls[0][1][0]) == {
- '1': 'light.test',
- }
-
- number = conf.entity_id_to_number('light.test')
- assert number == '1'
- assert handle.write.call_count == 1
-
- number = conf.entity_id_to_number('light.test2')
- assert number == '2'
- assert handle.write.call_count == 2
-
- entity_id = conf.number_to_entity_id('2')
- assert entity_id == 'light.test2'
-
-
-def test_config_alexa_entity_id_to_number():
- """Test config adheres to the type."""
- conf = Config(None, {
- 'type': 'alexa'
- })
-
- number = conf.entity_id_to_number('light.test')
- assert number == 'light.test'
-
- number = conf.entity_id_to_number('light.test')
- assert number == 'light.test'
-
- number = conf.entity_id_to_number('light.test2')
- assert number == 'light.test2'
-
- entity_id = conf.number_to_entity_id('light.test')
- assert entity_id == 'light.test'
-
-
-def test_warning_config_google_home_listen_port():
- """Test we warn when non-default port is used for Google Home."""
- with patch.object(_LOGGER, 'warning') as mock_warn:
- Config(None, {
- 'type': 'google_home',
- 'host_ip': '123.123.123.123',
- 'listen_port': 8300
- })
-
- assert mock_warn.called
- assert mock_warn.mock_calls[0][1][0] == \
- "When targeting Google Home, listening port has to be port 80"
+"""Test the Emulated Hue component."""
+import json
+
+from unittest.mock import patch, Mock, mock_open
+
+from homeassistant.components.emulated_hue import Config, _LOGGER
+
+
+def test_config_google_home_entity_id_to_number():
+ """Test config adheres to the type."""
+ conf = Config(Mock(), {
+ 'type': 'google_home'
+ })
+
+ mop = mock_open(read_data=json.dumps({'1': 'light.test2'}))
+ handle = mop()
+
+ with patch('homeassistant.util.json.open', mop, create=True):
+ number = conf.entity_id_to_number('light.test')
+ assert number == '2'
+ assert handle.write.call_count == 1
+ assert json.loads(handle.write.mock_calls[0][1][0]) == {
+ '1': 'light.test2',
+ '2': 'light.test',
+ }
+
+ number = conf.entity_id_to_number('light.test')
+ assert number == '2'
+ assert handle.write.call_count == 1
+
+ number = conf.entity_id_to_number('light.test2')
+ assert number == '1'
+ assert handle.write.call_count == 1
+
+ entity_id = conf.number_to_entity_id('1')
+ assert entity_id == 'light.test2'
+
+
+def test_config_google_home_entity_id_to_number_altered():
+ """Test config adheres to the type."""
+ conf = Config(Mock(), {
+ 'type': 'google_home'
+ })
+
+ mop = mock_open(read_data=json.dumps({'21': 'light.test2'}))
+ handle = mop()
+
+ with patch('homeassistant.util.json.open', mop, create=True):
+ number = conf.entity_id_to_number('light.test')
+ assert number == '22'
+ assert handle.write.call_count == 1
+ assert json.loads(handle.write.mock_calls[0][1][0]) == {
+ '21': 'light.test2',
+ '22': 'light.test',
+ }
+
+ number = conf.entity_id_to_number('light.test')
+ assert number == '22'
+ assert handle.write.call_count == 1
+
+ number = conf.entity_id_to_number('light.test2')
+ assert number == '21'
+ assert handle.write.call_count == 1
+
+ entity_id = conf.number_to_entity_id('21')
+ assert entity_id == 'light.test2'
+
+
+def test_config_google_home_entity_id_to_number_empty():
+ """Test config adheres to the type."""
+ conf = Config(Mock(), {
+ 'type': 'google_home'
+ })
+
+ mop = mock_open(read_data='')
+ handle = mop()
+
+ with patch('homeassistant.util.json.open', mop, create=True):
+ number = conf.entity_id_to_number('light.test')
+ assert number == '1'
+ assert handle.write.call_count == 1
+ assert json.loads(handle.write.mock_calls[0][1][0]) == {
+ '1': 'light.test',
+ }
+
+ number = conf.entity_id_to_number('light.test')
+ assert number == '1'
+ assert handle.write.call_count == 1
+
+ number = conf.entity_id_to_number('light.test2')
+ assert number == '2'
+ assert handle.write.call_count == 2
+
+ entity_id = conf.number_to_entity_id('2')
+ assert entity_id == 'light.test2'
+
+
+def test_config_alexa_entity_id_to_number():
+ """Test config adheres to the type."""
+ conf = Config(None, {
+ 'type': 'alexa'
+ })
+
+ number = conf.entity_id_to_number('light.test')
+ assert number == 'light.test'
+
+ number = conf.entity_id_to_number('light.test')
+ assert number == 'light.test'
+
+ number = conf.entity_id_to_number('light.test2')
+ assert number == 'light.test2'
+
+ entity_id = conf.number_to_entity_id('light.test')
+ assert entity_id == 'light.test'
+
+
+def test_warning_config_google_home_listen_port():
+ """Test we warn when non-default port is used for Google Home."""
+ with patch.object(_LOGGER, 'warning') as mock_warn:
+ Config(None, {
+ 'type': 'google_home',
+ 'host_ip': '123.123.123.123',
+ 'listen_port': 8300
+ })
+
+ assert mock_warn.called
+ assert mock_warn.mock_calls[0][1][0] == \
+ "When targeting Google Home, listening port has to be port 80"
diff --git a/tests/components/light/test_mqtt_json.py b/tests/components/light/test_mqtt_json.py
index 5cb0d0cdc1b..a06f8e7d093 100644
--- a/tests/components/light/test_mqtt_json.py
+++ b/tests/components/light/test_mqtt_json.py
@@ -1,579 +1,579 @@
-"""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.assertEqual(('test_light_rgb/set', '{"state": "ON"}', 2, False),
- self.mock_publish.mock_calls[-2][1])
- 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.assertEqual(('test_light_rgb/set', '{"state": "OFF"}', 2, False),
- self.mock_publish.mock_calls[-2][1])
- 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.mock_calls[-2][1][0])
- self.assertEqual(2, self.mock_publish.mock_calls[-2][1][2])
- self.assertEqual(False, self.mock_publish.mock_calls[-2][1][3])
- # Get the sent message
- message_json = json.loads(self.mock_publish.mock_calls[-2][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.mock_calls[-2][1][0])
- self.assertEqual(0, self.mock_publish.mock_calls[-2][1][2])
- self.assertEqual(False, self.mock_publish.mock_calls[-2][1][3])
- # Get the sent message
- message_json = json.loads(self.mock_publish.mock_calls[-2][1][1])
- self.assertEqual(5, message_json["flash"])
- self.assertEqual("ON", message_json["state"])
-
- light.turn_on(self.hass, 'light.test', flash="long")
- self.hass.block_till_done()
-
- self.assertEqual('test_light_rgb/set',
- self.mock_publish.mock_calls[-2][1][0])
- self.assertEqual(0, self.mock_publish.mock_calls[-2][1][2])
- self.assertEqual(False, self.mock_publish.mock_calls[-2][1][3])
- # Get the sent message
- message_json = json.loads(self.mock_publish.mock_calls[-2][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.mock_calls[-2][1][0])
- self.assertEqual(0, self.mock_publish.mock_calls[-2][1][2])
- self.assertEqual(False, self.mock_publish.mock_calls[-2][1][3])
- # Get the sent message
- message_json = json.loads(self.mock_publish.mock_calls[-2][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.mock_calls[-2][1][0])
- self.assertEqual(0, self.mock_publish.mock_calls[-2][1][2])
- self.assertEqual(False, self.mock_publish.mock_calls[-2][1][3])
- # Get the sent message
- message_json = json.loads(self.mock_publish.mock_calls[-2][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.assertEqual(('test_light_rgb/set', '{"state": "ON"}', 2, False),
+ self.mock_publish.mock_calls[-2][1])
+ 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.assertEqual(('test_light_rgb/set', '{"state": "OFF"}', 2, False),
+ self.mock_publish.mock_calls[-2][1])
+ 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.mock_calls[-2][1][0])
+ self.assertEqual(2, self.mock_publish.mock_calls[-2][1][2])
+ self.assertEqual(False, self.mock_publish.mock_calls[-2][1][3])
+ # Get the sent message
+ message_json = json.loads(self.mock_publish.mock_calls[-2][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.mock_calls[-2][1][0])
+ self.assertEqual(0, self.mock_publish.mock_calls[-2][1][2])
+ self.assertEqual(False, self.mock_publish.mock_calls[-2][1][3])
+ # Get the sent message
+ message_json = json.loads(self.mock_publish.mock_calls[-2][1][1])
+ self.assertEqual(5, message_json["flash"])
+ self.assertEqual("ON", message_json["state"])
+
+ light.turn_on(self.hass, 'light.test', flash="long")
+ self.hass.block_till_done()
+
+ self.assertEqual('test_light_rgb/set',
+ self.mock_publish.mock_calls[-2][1][0])
+ self.assertEqual(0, self.mock_publish.mock_calls[-2][1][2])
+ self.assertEqual(False, self.mock_publish.mock_calls[-2][1][3])
+ # Get the sent message
+ message_json = json.loads(self.mock_publish.mock_calls[-2][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.mock_calls[-2][1][0])
+ self.assertEqual(0, self.mock_publish.mock_calls[-2][1][2])
+ self.assertEqual(False, self.mock_publish.mock_calls[-2][1][3])
+ # Get the sent message
+ message_json = json.loads(self.mock_publish.mock_calls[-2][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.mock_calls[-2][1][0])
+ self.assertEqual(0, self.mock_publish.mock_calls[-2][1][2])
+ self.assertEqual(False, self.mock_publish.mock_calls[-2][1][3])
+ # Get the sent message
+ message_json = json.loads(self.mock_publish.mock_calls[-2][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 be1f119fc14..0df9d8136e1 100644
--- a/tests/components/light/test_mqtt_template.py
+++ b/tests/components/light/test_mqtt_template.py
@@ -1,524 +1,524 @@
-"""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.assertEqual(('test_light_rgb/set', 'on,,,,--', 2, False),
- self.mock_publish.mock_calls[-2][1])
- 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.assertEqual(('test_light_rgb/set', 'off', 2, False),
- self.mock_publish.mock_calls[-2][1])
- 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.assertEqual('test_light_rgb/set',
- self.mock_publish.mock_calls[-2][1][0])
-
- # check the payload
- payload = self.mock_publish.mock_calls[-2][1][1]
- self.assertEqual('on,50,,,75-75-75', payload)
-
- # 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()
-
- payload = self.mock_publish.mock_calls[-2][1][1]
- self.assertEqual('on,,200,139,--', payload)
-
- self.assertEqual(2, self.mock_publish.mock_calls[-2][1][2])
- self.assertEqual(False, self.mock_publish.mock_calls[-2][1][3])
-
- # 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.assertEqual('test_light_rgb/set',
- self.mock_publish.mock_calls[-2][1][0])
- self.assertEqual(0, self.mock_publish.mock_calls[-2][1][2])
- self.assertEqual(False, self.mock_publish.mock_calls[-2][1][3])
-
- # check the payload
- payload = self.mock_publish.mock_calls[-2][1][1]
- self.assertEqual('on,short', payload)
-
- # long flash
- light.turn_on(self.hass, 'light.test', flash='long')
- self.hass.block_till_done()
-
- self.assertEqual('test_light_rgb/set',
- self.mock_publish.mock_calls[-2][1][0])
- self.assertEqual(0, self.mock_publish.mock_calls[-2][1][2])
- self.assertEqual(False, self.mock_publish.mock_calls[-2][1][3])
-
- # check the payload
- payload = self.mock_publish.mock_calls[-2][1][1]
- self.assertEqual('on,long', payload)
-
- 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.assertEqual('test_light_rgb/set',
- self.mock_publish.mock_calls[-2][1][0])
- self.assertEqual(0, self.mock_publish.mock_calls[-2][1][2])
- self.assertEqual(False, self.mock_publish.mock_calls[-2][1][3])
-
- # check the payload
- payload = self.mock_publish.mock_calls[-2][1][1]
- self.assertEqual('on,10', payload)
-
- # transition off
- light.turn_off(self.hass, 'light.test', transition=4)
- self.hass.block_till_done()
-
- self.assertEqual('test_light_rgb/set',
- self.mock_publish.mock_calls[-2][1][0])
- self.assertEqual(0, self.mock_publish.mock_calls[-2][1][2])
- self.assertEqual(False, self.mock_publish.mock_calls[-2][1][3])
-
- # check the payload
- payload = self.mock_publish.mock_calls[-2][1][1]
- self.assertEqual('off,4', payload)
-
- 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.assertEqual(('test_light_rgb/set', 'on,,,,--', 2, False),
+ self.mock_publish.mock_calls[-2][1])
+ 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.assertEqual(('test_light_rgb/set', 'off', 2, False),
+ self.mock_publish.mock_calls[-2][1])
+ 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.assertEqual('test_light_rgb/set',
+ self.mock_publish.mock_calls[-2][1][0])
+
+ # check the payload
+ payload = self.mock_publish.mock_calls[-2][1][1]
+ self.assertEqual('on,50,,,75-75-75', payload)
+
+ # 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()
+
+ payload = self.mock_publish.mock_calls[-2][1][1]
+ self.assertEqual('on,,200,139,--', payload)
+
+ self.assertEqual(2, self.mock_publish.mock_calls[-2][1][2])
+ self.assertEqual(False, self.mock_publish.mock_calls[-2][1][3])
+
+ # 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.assertEqual('test_light_rgb/set',
+ self.mock_publish.mock_calls[-2][1][0])
+ self.assertEqual(0, self.mock_publish.mock_calls[-2][1][2])
+ self.assertEqual(False, self.mock_publish.mock_calls[-2][1][3])
+
+ # check the payload
+ payload = self.mock_publish.mock_calls[-2][1][1]
+ self.assertEqual('on,short', payload)
+
+ # long flash
+ light.turn_on(self.hass, 'light.test', flash='long')
+ self.hass.block_till_done()
+
+ self.assertEqual('test_light_rgb/set',
+ self.mock_publish.mock_calls[-2][1][0])
+ self.assertEqual(0, self.mock_publish.mock_calls[-2][1][2])
+ self.assertEqual(False, self.mock_publish.mock_calls[-2][1][3])
+
+ # check the payload
+ payload = self.mock_publish.mock_calls[-2][1][1]
+ self.assertEqual('on,long', payload)
+
+ 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.assertEqual('test_light_rgb/set',
+ self.mock_publish.mock_calls[-2][1][0])
+ self.assertEqual(0, self.mock_publish.mock_calls[-2][1][2])
+ self.assertEqual(False, self.mock_publish.mock_calls[-2][1][3])
+
+ # check the payload
+ payload = self.mock_publish.mock_calls[-2][1][1]
+ self.assertEqual('on,10', payload)
+
+ # transition off
+ light.turn_off(self.hass, 'light.test', transition=4)
+ self.hass.block_till_done()
+
+ self.assertEqual('test_light_rgb/set',
+ self.mock_publish.mock_calls[-2][1][0])
+ self.assertEqual(0, self.mock_publish.mock_calls[-2][1][2])
+ self.assertEqual(False, self.mock_publish.mock_calls[-2][1][3])
+
+ # check the payload
+ payload = self.mock_publish.mock_calls[-2][1][1]
+ self.assertEqual('off,4', payload)
+
+ 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/components/sensor/test_hddtemp.py b/tests/components/sensor/test_hddtemp.py
index 3be35f3281c..1b65af7fd7e 100644
--- a/tests/components/sensor/test_hddtemp.py
+++ b/tests/components/sensor/test_hddtemp.py
@@ -1,216 +1,216 @@
-"""The tests for the hddtemp platform."""
-import socket
-
-import unittest
-from unittest.mock import patch
-
-from homeassistant.setup import setup_component
-
-from tests.common import get_test_home_assistant
-
-VALID_CONFIG_MINIMAL = {
- 'sensor': {
- 'platform': 'hddtemp',
- }
-}
-
-VALID_CONFIG_NAME = {
- 'sensor': {
- 'platform': 'hddtemp',
- 'name': 'FooBar',
- }
-}
-
-VALID_CONFIG_ONE_DISK = {
- 'sensor': {
- 'platform': 'hddtemp',
- 'disks': [
- '/dev/sdd1',
- ],
- }
-}
-
-VALID_CONFIG_WRONG_DISK = {
- 'sensor': {
- 'platform': 'hddtemp',
- 'disks': [
- '/dev/sdx1',
- ],
- }
-}
-
-VALID_CONFIG_MULTIPLE_DISKS = {
- 'sensor': {
- 'platform': 'hddtemp',
- 'host': 'foobar.local',
- 'disks': [
- '/dev/sda1',
- '/dev/sdb1',
- '/dev/sdc1',
- ],
- }
-}
-
-VALID_CONFIG_HOST = {
- 'sensor': {
- 'platform': 'hddtemp',
- 'host': 'alice.local',
- }
-}
-
-VALID_CONFIG_HOST_UNREACHABLE = {
- 'sensor': {
- 'platform': 'hddtemp',
- 'host': 'bob.local',
- }
-}
-
-
-class TelnetMock():
- """Mock class for the telnetlib.Telnet object."""
-
- def __init__(self, host, port, timeout=0):
- """Initialize Telnet object."""
- self.host = host
- self.port = port
- self.timeout = timeout
- self.sample_data = bytes('|/dev/sda1|WDC WD30EZRX-12DC0B0|29|C|' +
- '|/dev/sdb1|WDC WD15EADS-11P7B2|32|C|' +
- '|/dev/sdc1|WDC WD20EARX-22MMMB0|29|C|' +
- '|/dev/sdd1|WDC WD15EARS-00Z5B1|89|F|',
- 'ascii')
-
- def read_all(self):
- """Return sample values."""
- if self.host == 'alice.local':
- raise ConnectionRefusedError
- elif self.host == 'bob.local':
- raise socket.gaierror
- else:
- return self.sample_data
- return None
-
-
-class TestHDDTempSensor(unittest.TestCase):
- """Test the hddtemp sensor."""
-
- def setUp(self):
- """Set up things to run when tests begin."""
- self.hass = get_test_home_assistant()
- self.config = VALID_CONFIG_ONE_DISK
- self.reference = {'/dev/sda1': {'device': '/dev/sda1',
- 'temperature': '29',
- 'unit_of_measurement': '°C',
- 'model': 'WDC WD30EZRX-12DC0B0', },
- '/dev/sdb1': {'device': '/dev/sdb1',
- 'temperature': '32',
- 'unit_of_measurement': '°C',
- 'model': 'WDC WD15EADS-11P7B2', },
- '/dev/sdc1': {'device': '/dev/sdc1',
- 'temperature': '29',
- 'unit_of_measurement': '°C',
- 'model': 'WDC WD20EARX-22MMMB0', },
- '/dev/sdd1': {'device': '/dev/sdd1',
- 'temperature': '32',
- 'unit_of_measurement': '°C',
- 'model': 'WDC WD15EARS-00Z5B1', }, }
-
- def tearDown(self):
- """Stop everything that was started."""
- self.hass.stop()
-
- @patch('telnetlib.Telnet', new=TelnetMock)
- def test_hddtemp_min_config(self):
- """Test minimal hddtemp configuration."""
- assert setup_component(self.hass, 'sensor', VALID_CONFIG_MINIMAL)
-
- entity = self.hass.states.all()[0].entity_id
- state = self.hass.states.get(entity)
-
- reference = self.reference[state.attributes.get('device')]
-
- self.assertEqual(state.state, reference['temperature'])
- self.assertEqual(state.attributes.get('device'), reference['device'])
- self.assertEqual(state.attributes.get('model'), reference['model'])
- self.assertEqual(state.attributes.get('unit_of_measurement'),
- reference['unit_of_measurement'])
- self.assertEqual(state.attributes.get('friendly_name'),
- 'HD Temperature ' + reference['device'])
-
- @patch('telnetlib.Telnet', new=TelnetMock)
- def test_hddtemp_rename_config(self):
- """Test hddtemp configuration with different name."""
- assert setup_component(self.hass, 'sensor', VALID_CONFIG_NAME)
-
- entity = self.hass.states.all()[0].entity_id
- state = self.hass.states.get(entity)
-
- reference = self.reference[state.attributes.get('device')]
-
- self.assertEqual(state.attributes.get('friendly_name'),
- 'FooBar ' + reference['device'])
-
- @patch('telnetlib.Telnet', new=TelnetMock)
- def test_hddtemp_one_disk(self):
- """Test hddtemp one disk configuration."""
- assert setup_component(self.hass, 'sensor', VALID_CONFIG_ONE_DISK)
-
- state = self.hass.states.get('sensor.hd_temperature_devsdd1')
-
- reference = self.reference[state.attributes.get('device')]
-
- self.assertEqual(state.state, reference['temperature'])
- self.assertEqual(state.attributes.get('device'), reference['device'])
- self.assertEqual(state.attributes.get('model'), reference['model'])
- self.assertEqual(state.attributes.get('unit_of_measurement'),
- reference['unit_of_measurement'])
- self.assertEqual(state.attributes.get('friendly_name'),
- 'HD Temperature ' + reference['device'])
-
- @patch('telnetlib.Telnet', new=TelnetMock)
- def test_hddtemp_wrong_disk(self):
- """Test hddtemp wrong disk configuration."""
- assert setup_component(self.hass, 'sensor', VALID_CONFIG_WRONG_DISK)
-
- self.assertEqual(len(self.hass.states.all()), 1)
- state = self.hass.states.get('sensor.hd_temperature_devsdx1')
- self.assertEqual(state.attributes.get('friendly_name'),
- 'HD Temperature ' + '/dev/sdx1')
-
- @patch('telnetlib.Telnet', new=TelnetMock)
- def test_hddtemp_multiple_disks(self):
- """Test hddtemp multiple disk configuration."""
- assert setup_component(self.hass,
- 'sensor', VALID_CONFIG_MULTIPLE_DISKS)
-
- for sensor in ['sensor.hd_temperature_devsda1',
- 'sensor.hd_temperature_devsdb1',
- 'sensor.hd_temperature_devsdc1']:
-
- state = self.hass.states.get(sensor)
-
- reference = self.reference[state.attributes.get('device')]
-
- self.assertEqual(state.state,
- reference['temperature'])
- self.assertEqual(state.attributes.get('device'),
- reference['device'])
- self.assertEqual(state.attributes.get('model'),
- reference['model'])
- self.assertEqual(state.attributes.get('unit_of_measurement'),
- reference['unit_of_measurement'])
- self.assertEqual(state.attributes.get('friendly_name'),
- 'HD Temperature ' + reference['device'])
-
- @patch('telnetlib.Telnet', new=TelnetMock)
- def test_hddtemp_host_refused(self):
- """Test hddtemp if host unreachable."""
- assert setup_component(self.hass, 'sensor', VALID_CONFIG_HOST)
- self.assertEqual(len(self.hass.states.all()), 0)
-
- @patch('telnetlib.Telnet', new=TelnetMock)
- def test_hddtemp_host_unreachable(self):
- """Test hddtemp if host unreachable."""
- assert setup_component(self.hass, 'sensor',
- VALID_CONFIG_HOST_UNREACHABLE)
- self.assertEqual(len(self.hass.states.all()), 0)
+"""The tests for the hddtemp platform."""
+import socket
+
+import unittest
+from unittest.mock import patch
+
+from homeassistant.setup import setup_component
+
+from tests.common import get_test_home_assistant
+
+VALID_CONFIG_MINIMAL = {
+ 'sensor': {
+ 'platform': 'hddtemp',
+ }
+}
+
+VALID_CONFIG_NAME = {
+ 'sensor': {
+ 'platform': 'hddtemp',
+ 'name': 'FooBar',
+ }
+}
+
+VALID_CONFIG_ONE_DISK = {
+ 'sensor': {
+ 'platform': 'hddtemp',
+ 'disks': [
+ '/dev/sdd1',
+ ],
+ }
+}
+
+VALID_CONFIG_WRONG_DISK = {
+ 'sensor': {
+ 'platform': 'hddtemp',
+ 'disks': [
+ '/dev/sdx1',
+ ],
+ }
+}
+
+VALID_CONFIG_MULTIPLE_DISKS = {
+ 'sensor': {
+ 'platform': 'hddtemp',
+ 'host': 'foobar.local',
+ 'disks': [
+ '/dev/sda1',
+ '/dev/sdb1',
+ '/dev/sdc1',
+ ],
+ }
+}
+
+VALID_CONFIG_HOST = {
+ 'sensor': {
+ 'platform': 'hddtemp',
+ 'host': 'alice.local',
+ }
+}
+
+VALID_CONFIG_HOST_UNREACHABLE = {
+ 'sensor': {
+ 'platform': 'hddtemp',
+ 'host': 'bob.local',
+ }
+}
+
+
+class TelnetMock():
+ """Mock class for the telnetlib.Telnet object."""
+
+ def __init__(self, host, port, timeout=0):
+ """Initialize Telnet object."""
+ self.host = host
+ self.port = port
+ self.timeout = timeout
+ self.sample_data = bytes('|/dev/sda1|WDC WD30EZRX-12DC0B0|29|C|' +
+ '|/dev/sdb1|WDC WD15EADS-11P7B2|32|C|' +
+ '|/dev/sdc1|WDC WD20EARX-22MMMB0|29|C|' +
+ '|/dev/sdd1|WDC WD15EARS-00Z5B1|89|F|',
+ 'ascii')
+
+ def read_all(self):
+ """Return sample values."""
+ if self.host == 'alice.local':
+ raise ConnectionRefusedError
+ elif self.host == 'bob.local':
+ raise socket.gaierror
+ else:
+ return self.sample_data
+ return None
+
+
+class TestHDDTempSensor(unittest.TestCase):
+ """Test the hddtemp sensor."""
+
+ def setUp(self):
+ """Set up things to run when tests begin."""
+ self.hass = get_test_home_assistant()
+ self.config = VALID_CONFIG_ONE_DISK
+ self.reference = {'/dev/sda1': {'device': '/dev/sda1',
+ 'temperature': '29',
+ 'unit_of_measurement': '°C',
+ 'model': 'WDC WD30EZRX-12DC0B0', },
+ '/dev/sdb1': {'device': '/dev/sdb1',
+ 'temperature': '32',
+ 'unit_of_measurement': '°C',
+ 'model': 'WDC WD15EADS-11P7B2', },
+ '/dev/sdc1': {'device': '/dev/sdc1',
+ 'temperature': '29',
+ 'unit_of_measurement': '°C',
+ 'model': 'WDC WD20EARX-22MMMB0', },
+ '/dev/sdd1': {'device': '/dev/sdd1',
+ 'temperature': '32',
+ 'unit_of_measurement': '°C',
+ 'model': 'WDC WD15EARS-00Z5B1', }, }
+
+ def tearDown(self):
+ """Stop everything that was started."""
+ self.hass.stop()
+
+ @patch('telnetlib.Telnet', new=TelnetMock)
+ def test_hddtemp_min_config(self):
+ """Test minimal hddtemp configuration."""
+ assert setup_component(self.hass, 'sensor', VALID_CONFIG_MINIMAL)
+
+ entity = self.hass.states.all()[0].entity_id
+ state = self.hass.states.get(entity)
+
+ reference = self.reference[state.attributes.get('device')]
+
+ self.assertEqual(state.state, reference['temperature'])
+ self.assertEqual(state.attributes.get('device'), reference['device'])
+ self.assertEqual(state.attributes.get('model'), reference['model'])
+ self.assertEqual(state.attributes.get('unit_of_measurement'),
+ reference['unit_of_measurement'])
+ self.assertEqual(state.attributes.get('friendly_name'),
+ 'HD Temperature ' + reference['device'])
+
+ @patch('telnetlib.Telnet', new=TelnetMock)
+ def test_hddtemp_rename_config(self):
+ """Test hddtemp configuration with different name."""
+ assert setup_component(self.hass, 'sensor', VALID_CONFIG_NAME)
+
+ entity = self.hass.states.all()[0].entity_id
+ state = self.hass.states.get(entity)
+
+ reference = self.reference[state.attributes.get('device')]
+
+ self.assertEqual(state.attributes.get('friendly_name'),
+ 'FooBar ' + reference['device'])
+
+ @patch('telnetlib.Telnet', new=TelnetMock)
+ def test_hddtemp_one_disk(self):
+ """Test hddtemp one disk configuration."""
+ assert setup_component(self.hass, 'sensor', VALID_CONFIG_ONE_DISK)
+
+ state = self.hass.states.get('sensor.hd_temperature_devsdd1')
+
+ reference = self.reference[state.attributes.get('device')]
+
+ self.assertEqual(state.state, reference['temperature'])
+ self.assertEqual(state.attributes.get('device'), reference['device'])
+ self.assertEqual(state.attributes.get('model'), reference['model'])
+ self.assertEqual(state.attributes.get('unit_of_measurement'),
+ reference['unit_of_measurement'])
+ self.assertEqual(state.attributes.get('friendly_name'),
+ 'HD Temperature ' + reference['device'])
+
+ @patch('telnetlib.Telnet', new=TelnetMock)
+ def test_hddtemp_wrong_disk(self):
+ """Test hddtemp wrong disk configuration."""
+ assert setup_component(self.hass, 'sensor', VALID_CONFIG_WRONG_DISK)
+
+ self.assertEqual(len(self.hass.states.all()), 1)
+ state = self.hass.states.get('sensor.hd_temperature_devsdx1')
+ self.assertEqual(state.attributes.get('friendly_name'),
+ 'HD Temperature ' + '/dev/sdx1')
+
+ @patch('telnetlib.Telnet', new=TelnetMock)
+ def test_hddtemp_multiple_disks(self):
+ """Test hddtemp multiple disk configuration."""
+ assert setup_component(self.hass,
+ 'sensor', VALID_CONFIG_MULTIPLE_DISKS)
+
+ for sensor in ['sensor.hd_temperature_devsda1',
+ 'sensor.hd_temperature_devsdb1',
+ 'sensor.hd_temperature_devsdc1']:
+
+ state = self.hass.states.get(sensor)
+
+ reference = self.reference[state.attributes.get('device')]
+
+ self.assertEqual(state.state,
+ reference['temperature'])
+ self.assertEqual(state.attributes.get('device'),
+ reference['device'])
+ self.assertEqual(state.attributes.get('model'),
+ reference['model'])
+ self.assertEqual(state.attributes.get('unit_of_measurement'),
+ reference['unit_of_measurement'])
+ self.assertEqual(state.attributes.get('friendly_name'),
+ 'HD Temperature ' + reference['device'])
+
+ @patch('telnetlib.Telnet', new=TelnetMock)
+ def test_hddtemp_host_refused(self):
+ """Test hddtemp if host unreachable."""
+ assert setup_component(self.hass, 'sensor', VALID_CONFIG_HOST)
+ self.assertEqual(len(self.hass.states.all()), 0)
+
+ @patch('telnetlib.Telnet', new=TelnetMock)
+ def test_hddtemp_host_unreachable(self):
+ """Test hddtemp if host unreachable."""
+ assert setup_component(self.hass, 'sensor',
+ VALID_CONFIG_HOST_UNREACHABLE)
+ self.assertEqual(len(self.hass.states.all()), 0)
diff --git a/tests/components/switch/test_wake_on_lan.py b/tests/components/switch/test_wake_on_lan.py
index d7945218e73..167c3bb35ac 100644
--- a/tests/components/switch/test_wake_on_lan.py
+++ b/tests/components/switch/test_wake_on_lan.py
@@ -1,192 +1,192 @@
-"""The tests for the wake on lan switch platform."""
-import unittest
-from unittest.mock import patch
-
-from homeassistant.setup import setup_component
-from homeassistant.const import STATE_ON, STATE_OFF
-import homeassistant.components.switch as switch
-
-from tests.common import get_test_home_assistant, mock_service
-
-
-TEST_STATE = None
-
-
-def send_magic_packet(*macs, **kwargs):
- """Fake call for sending magic packets."""
- return
-
-
-def call(cmd, stdout, stderr):
- """Return fake subprocess return codes."""
- if cmd[5] == 'validhostname' and TEST_STATE:
- return 0
- return 2
-
-
-def system():
- """Fake system call to test the windows platform."""
- return 'Windows'
-
-
-class TestWOLSwitch(unittest.TestCase):
- """Test the wol switch."""
-
- def setUp(self):
- """Setup things to be run when tests are started."""
- self.hass = get_test_home_assistant()
-
- def tearDown(self):
- """Stop everything that was started."""
- self.hass.stop()
-
- @patch('wakeonlan.send_magic_packet', new=send_magic_packet)
- @patch('subprocess.call', new=call)
- def test_valid_hostname(self):
- """Test with valid hostname."""
- global TEST_STATE
- TEST_STATE = False
- self.assertTrue(setup_component(self.hass, switch.DOMAIN, {
- 'switch': {
- 'platform': 'wake_on_lan',
- 'mac_address': '00-01-02-03-04-05',
- 'host': 'validhostname',
- }
- }))
-
- state = self.hass.states.get('switch.wake_on_lan')
- self.assertEqual(STATE_OFF, state.state)
-
- TEST_STATE = True
-
- switch.turn_on(self.hass, 'switch.wake_on_lan')
- self.hass.block_till_done()
-
- state = self.hass.states.get('switch.wake_on_lan')
- self.assertEqual(STATE_ON, state.state)
-
- switch.turn_off(self.hass, 'switch.wake_on_lan')
- self.hass.block_till_done()
-
- state = self.hass.states.get('switch.wake_on_lan')
- self.assertEqual(STATE_ON, state.state)
-
- @patch('wakeonlan.send_magic_packet', new=send_magic_packet)
- @patch('subprocess.call', new=call)
- @patch('platform.system', new=system)
- def test_valid_hostname_windows(self):
- """Test with valid hostname on windows."""
- global TEST_STATE
- TEST_STATE = False
- self.assertTrue(setup_component(self.hass, switch.DOMAIN, {
- 'switch': {
- 'platform': 'wake_on_lan',
- 'mac_address': '00-01-02-03-04-05',
- 'host': 'validhostname',
- }
- }))
-
- state = self.hass.states.get('switch.wake_on_lan')
- self.assertEqual(STATE_OFF, state.state)
-
- TEST_STATE = True
-
- switch.turn_on(self.hass, 'switch.wake_on_lan')
- self.hass.block_till_done()
-
- state = self.hass.states.get('switch.wake_on_lan')
- self.assertEqual(STATE_ON, state.state)
-
- @patch('wakeonlan.send_magic_packet', new=send_magic_packet)
- @patch('subprocess.call', new=call)
- def test_minimal_config(self):
- """Test with minimal config."""
- self.assertTrue(setup_component(self.hass, switch.DOMAIN, {
- 'switch': {
- 'platform': 'wake_on_lan',
- 'mac_address': '00-01-02-03-04-05',
- }
- }))
-
- @patch('wakeonlan.send_magic_packet', new=send_magic_packet)
- @patch('subprocess.call', new=call)
- def test_broadcast_config(self):
- """Test with broadcast address config."""
- self.assertTrue(setup_component(self.hass, switch.DOMAIN, {
- 'switch': {
- 'platform': 'wake_on_lan',
- 'mac_address': '00-01-02-03-04-05',
- 'broadcast_address': '255.255.255.255',
- }
- }))
-
- state = self.hass.states.get('switch.wake_on_lan')
- self.assertEqual(STATE_OFF, state.state)
-
- switch.turn_on(self.hass, 'switch.wake_on_lan')
- self.hass.block_till_done()
-
- @patch('wakeonlan.send_magic_packet', new=send_magic_packet)
- @patch('subprocess.call', new=call)
- def test_off_script(self):
- """Test with turn off script."""
- global TEST_STATE
- TEST_STATE = False
- self.assertTrue(setup_component(self.hass, switch.DOMAIN, {
- 'switch': {
- 'platform': 'wake_on_lan',
- 'mac_address': '00-01-02-03-04-05',
- 'host': 'validhostname',
- 'turn_off': {
- 'service': 'shell_command.turn_off_TARGET',
- },
- }
- }))
- calls = mock_service(self.hass, 'shell_command', 'turn_off_TARGET')
-
- state = self.hass.states.get('switch.wake_on_lan')
- self.assertEqual(STATE_OFF, state.state)
-
- TEST_STATE = True
-
- switch.turn_on(self.hass, 'switch.wake_on_lan')
- self.hass.block_till_done()
-
- state = self.hass.states.get('switch.wake_on_lan')
- self.assertEqual(STATE_ON, state.state)
- assert len(calls) == 0
-
- TEST_STATE = False
-
- switch.turn_off(self.hass, 'switch.wake_on_lan')
- self.hass.block_till_done()
-
- state = self.hass.states.get('switch.wake_on_lan')
- self.assertEqual(STATE_OFF, state.state)
- assert len(calls) == 1
-
- @patch('wakeonlan.send_magic_packet', new=send_magic_packet)
- @patch('subprocess.call', new=call)
- @patch('platform.system', new=system)
- def test_invalid_hostname_windows(self):
- """Test with invalid hostname on windows."""
- global TEST_STATE
- TEST_STATE = False
- self.assertTrue(setup_component(self.hass, switch.DOMAIN, {
- 'switch': {
- 'platform': 'wake_on_lan',
- 'mac_address': '00-01-02-03-04-05',
- 'host': 'invalidhostname',
- }
- }))
-
- state = self.hass.states.get('switch.wake_on_lan')
- self.assertEqual(STATE_OFF, state.state)
-
- TEST_STATE = True
-
- switch.turn_on(self.hass, 'switch.wake_on_lan')
- self.hass.block_till_done()
-
- state = self.hass.states.get('switch.wake_on_lan')
- self.assertEqual(STATE_OFF, state.state)
+"""The tests for the wake on lan switch platform."""
+import unittest
+from unittest.mock import patch
+
+from homeassistant.setup import setup_component
+from homeassistant.const import STATE_ON, STATE_OFF
+import homeassistant.components.switch as switch
+
+from tests.common import get_test_home_assistant, mock_service
+
+
+TEST_STATE = None
+
+
+def send_magic_packet(*macs, **kwargs):
+ """Fake call for sending magic packets."""
+ return
+
+
+def call(cmd, stdout, stderr):
+ """Return fake subprocess return codes."""
+ if cmd[5] == 'validhostname' and TEST_STATE:
+ return 0
+ return 2
+
+
+def system():
+ """Fake system call to test the windows platform."""
+ return 'Windows'
+
+
+class TestWOLSwitch(unittest.TestCase):
+ """Test the wol switch."""
+
+ def setUp(self):
+ """Setup things to be run when tests are started."""
+ self.hass = get_test_home_assistant()
+
+ def tearDown(self):
+ """Stop everything that was started."""
+ self.hass.stop()
+
+ @patch('wakeonlan.send_magic_packet', new=send_magic_packet)
+ @patch('subprocess.call', new=call)
+ def test_valid_hostname(self):
+ """Test with valid hostname."""
+ global TEST_STATE
+ TEST_STATE = False
+ self.assertTrue(setup_component(self.hass, switch.DOMAIN, {
+ 'switch': {
+ 'platform': 'wake_on_lan',
+ 'mac_address': '00-01-02-03-04-05',
+ 'host': 'validhostname',
+ }
+ }))
+
+ state = self.hass.states.get('switch.wake_on_lan')
+ self.assertEqual(STATE_OFF, state.state)
+
+ TEST_STATE = True
+
+ switch.turn_on(self.hass, 'switch.wake_on_lan')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('switch.wake_on_lan')
+ self.assertEqual(STATE_ON, state.state)
+
+ switch.turn_off(self.hass, 'switch.wake_on_lan')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('switch.wake_on_lan')
+ self.assertEqual(STATE_ON, state.state)
+
+ @patch('wakeonlan.send_magic_packet', new=send_magic_packet)
+ @patch('subprocess.call', new=call)
+ @patch('platform.system', new=system)
+ def test_valid_hostname_windows(self):
+ """Test with valid hostname on windows."""
+ global TEST_STATE
+ TEST_STATE = False
+ self.assertTrue(setup_component(self.hass, switch.DOMAIN, {
+ 'switch': {
+ 'platform': 'wake_on_lan',
+ 'mac_address': '00-01-02-03-04-05',
+ 'host': 'validhostname',
+ }
+ }))
+
+ state = self.hass.states.get('switch.wake_on_lan')
+ self.assertEqual(STATE_OFF, state.state)
+
+ TEST_STATE = True
+
+ switch.turn_on(self.hass, 'switch.wake_on_lan')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('switch.wake_on_lan')
+ self.assertEqual(STATE_ON, state.state)
+
+ @patch('wakeonlan.send_magic_packet', new=send_magic_packet)
+ @patch('subprocess.call', new=call)
+ def test_minimal_config(self):
+ """Test with minimal config."""
+ self.assertTrue(setup_component(self.hass, switch.DOMAIN, {
+ 'switch': {
+ 'platform': 'wake_on_lan',
+ 'mac_address': '00-01-02-03-04-05',
+ }
+ }))
+
+ @patch('wakeonlan.send_magic_packet', new=send_magic_packet)
+ @patch('subprocess.call', new=call)
+ def test_broadcast_config(self):
+ """Test with broadcast address config."""
+ self.assertTrue(setup_component(self.hass, switch.DOMAIN, {
+ 'switch': {
+ 'platform': 'wake_on_lan',
+ 'mac_address': '00-01-02-03-04-05',
+ 'broadcast_address': '255.255.255.255',
+ }
+ }))
+
+ state = self.hass.states.get('switch.wake_on_lan')
+ self.assertEqual(STATE_OFF, state.state)
+
+ switch.turn_on(self.hass, 'switch.wake_on_lan')
+ self.hass.block_till_done()
+
+ @patch('wakeonlan.send_magic_packet', new=send_magic_packet)
+ @patch('subprocess.call', new=call)
+ def test_off_script(self):
+ """Test with turn off script."""
+ global TEST_STATE
+ TEST_STATE = False
+ self.assertTrue(setup_component(self.hass, switch.DOMAIN, {
+ 'switch': {
+ 'platform': 'wake_on_lan',
+ 'mac_address': '00-01-02-03-04-05',
+ 'host': 'validhostname',
+ 'turn_off': {
+ 'service': 'shell_command.turn_off_TARGET',
+ },
+ }
+ }))
+ calls = mock_service(self.hass, 'shell_command', 'turn_off_TARGET')
+
+ state = self.hass.states.get('switch.wake_on_lan')
+ self.assertEqual(STATE_OFF, state.state)
+
+ TEST_STATE = True
+
+ switch.turn_on(self.hass, 'switch.wake_on_lan')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('switch.wake_on_lan')
+ self.assertEqual(STATE_ON, state.state)
+ assert len(calls) == 0
+
+ TEST_STATE = False
+
+ switch.turn_off(self.hass, 'switch.wake_on_lan')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('switch.wake_on_lan')
+ self.assertEqual(STATE_OFF, state.state)
+ assert len(calls) == 1
+
+ @patch('wakeonlan.send_magic_packet', new=send_magic_packet)
+ @patch('subprocess.call', new=call)
+ @patch('platform.system', new=system)
+ def test_invalid_hostname_windows(self):
+ """Test with invalid hostname on windows."""
+ global TEST_STATE
+ TEST_STATE = False
+ self.assertTrue(setup_component(self.hass, switch.DOMAIN, {
+ 'switch': {
+ 'platform': 'wake_on_lan',
+ 'mac_address': '00-01-02-03-04-05',
+ 'host': 'invalidhostname',
+ }
+ }))
+
+ state = self.hass.states.get('switch.wake_on_lan')
+ self.assertEqual(STATE_OFF, state.state)
+
+ TEST_STATE = True
+
+ switch.turn_on(self.hass, 'switch.wake_on_lan')
+ self.hass.block_till_done()
+
+ state = self.hass.states.get('switch.wake_on_lan')
+ self.assertEqual(STATE_OFF, state.state)