Merge pull request #4037 from home-assistant/remove-deprecated-things

Remove deprecated things
This commit is contained in:
Robbie Trencheny 2016-10-25 14:28:01 -07:00 committed by GitHub
commit 79da1ec0d9
51 changed files with 14 additions and 6416 deletions

View File

@ -159,8 +159,6 @@ omit =
homeassistant/components/fan/mqtt.py
homeassistant/components/feedreader.py
homeassistant/components/foursquare.py
homeassistant/components/garage_door/rpi_gpio.py
homeassistant/components/garage_door/wink.py
homeassistant/components/hdmi_cec.py
homeassistant/components/ifttt.py
homeassistant/components/joaoapps_join.py
@ -307,11 +305,6 @@ omit =
homeassistant/components/switch/tplink.py
homeassistant/components/switch/transmission.py
homeassistant/components/switch/wake_on_lan.py
homeassistant/components/thermostat/eq3btsmart.py
homeassistant/components/thermostat/heatmiser.py
homeassistant/components/thermostat/homematic.py
homeassistant/components/thermostat/proliphix.py
homeassistant/components/thermostat/radiotherm.py
homeassistant/components/upnp.py
homeassistant/components/weather/openweathermap.py
homeassistant/components/zeroconf.py

View File

@ -1,111 +0,0 @@
"""
Component to interface with garage doors that can be controlled remotely.
For more details about this component, please refer to the documentation
at https://home-assistant.io/components/garage_door/
"""
import logging
import os
import voluptuous as vol
from homeassistant.config import load_yaml_config_file
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa
import homeassistant.helpers.config_validation as cv
from homeassistant.const import (
STATE_CLOSED, STATE_OPEN, STATE_UNKNOWN, SERVICE_CLOSE, SERVICE_OPEN,
ATTR_ENTITY_ID)
from homeassistant.components import group
DOMAIN = 'garage_door'
SCAN_INTERVAL = 30
GROUP_NAME_ALL_GARAGE_DOORS = 'all garage doors'
ENTITY_ID_ALL_GARAGE_DOORS = group.ENTITY_ID_FORMAT.format('all_garage_doors')
ENTITY_ID_FORMAT = DOMAIN + '.{}'
GARAGE_DOOR_SERVICE_SCHEMA = vol.Schema({
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
})
_LOGGER = logging.getLogger(__name__)
def is_closed(hass, entity_id=None):
"""Return if the garage door is closed based on the statemachine."""
entity_id = entity_id or ENTITY_ID_ALL_GARAGE_DOORS
return hass.states.is_state(entity_id, STATE_CLOSED)
def close_door(hass, entity_id=None):
"""Close all or a specified garage door."""
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
hass.services.call(DOMAIN, SERVICE_CLOSE, data)
def open_door(hass, entity_id=None):
"""Open all or specified garage door."""
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
hass.services.call(DOMAIN, SERVICE_OPEN, data)
def setup(hass, config):
"""Track states and offer events for garage door."""
_LOGGER.warning('This component has been deprecated in favour of the '
'"cover" component and will be removed in the future.'
' Please upgrade.')
component = EntityComponent(
_LOGGER, DOMAIN, hass, SCAN_INTERVAL, GROUP_NAME_ALL_GARAGE_DOORS)
component.setup(config)
def handle_garage_door_service(service):
"""Handle calls to the garage door services."""
target_locks = component.extract_from_service(service)
for item in target_locks:
if service.service == SERVICE_CLOSE:
item.close_door()
else:
item.open_door()
if item.should_poll:
item.update_ha_state(True)
descriptions = load_yaml_config_file(
os.path.join(os.path.dirname(__file__), 'services.yaml'))
hass.services.register(DOMAIN, SERVICE_OPEN, handle_garage_door_service,
descriptions.get(SERVICE_OPEN),
schema=GARAGE_DOOR_SERVICE_SCHEMA)
hass.services.register(DOMAIN, SERVICE_CLOSE, handle_garage_door_service,
descriptions.get(SERVICE_CLOSE),
schema=GARAGE_DOOR_SERVICE_SCHEMA)
return True
class GarageDoorDevice(Entity):
"""Representation of a garage door."""
# pylint: disable=no-self-use
@property
def is_closed(self):
"""Return true if door is closed."""
return None
def close_door(self):
"""Close the garage door."""
raise NotImplementedError()
def open_door(self):
"""Open the garage door."""
raise NotImplementedError()
@property
def state(self):
"""Return the state of the garage door."""
closed = self.is_closed
if closed is None:
return STATE_UNKNOWN
return STATE_CLOSED if closed else STATE_OPEN

View File

@ -1,51 +0,0 @@
"""
Demo garage door platform that has two fake doors.
For more details about this platform, please refer to the documentation
https://home-assistant.io/components/demo/
"""
from homeassistant.components.garage_door import GarageDoorDevice
from homeassistant.const import STATE_CLOSED, STATE_OPEN
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
"""Setup demo garage door platform."""
add_devices_callback([
DemoGarageDoor('Left Garage Door', STATE_CLOSED),
DemoGarageDoor('Right Garage Door', STATE_OPEN)
])
class DemoGarageDoor(GarageDoorDevice):
"""Provides a demo garage door."""
def __init__(self, name, state):
"""Initialize the garage door."""
self._name = name
self._state = state
@property
def should_poll(self):
"""No polling needed for a demo garage door."""
return False
@property
def name(self):
"""Return the name of the device if any."""
return self._name
@property
def is_closed(self):
"""Return true if garage door is closed."""
return self._state == STATE_CLOSED
def close_door(self, **kwargs):
"""Close the garage door."""
self._state = STATE_CLOSED
self.update_ha_state()
def open_door(self, **kwargs):
"""Open the garage door."""
self._state = STATE_OPEN
self.update_ha_state()

View File

@ -1,141 +0,0 @@
"""
Support for MQTT garage doors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/garage_door.mqtt/
"""
import logging
import voluptuous as vol
from homeassistant.const import (STATE_OPEN, STATE_CLOSED, SERVICE_OPEN,
SERVICE_CLOSE)
import homeassistant.components.mqtt as mqtt
from homeassistant.components.garage_door import GarageDoorDevice
from homeassistant.const import (
CONF_NAME, CONF_OPTIMISTIC, CONF_VALUE_TEMPLATE)
from homeassistant.components.mqtt import (
CONF_STATE_TOPIC, CONF_COMMAND_TOPIC, CONF_QOS, CONF_RETAIN)
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
CONF_STATE_OPEN = 'state_open'
CONF_STATE_CLOSED = 'state_closed'
CONF_SERVICE_OPEN = 'service_open'
CONF_SERVICE_CLOSE = 'service_close'
DEFAULT_NAME = 'MQTT Garage Door'
DEFAULT_OPTIMISTIC = False
DEFAULT_RETAIN = False
DEPENDENCIES = ['mqtt']
PLATFORM_SCHEMA = mqtt.MQTT_RW_PLATFORM_SCHEMA.extend({
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
vol.Optional(CONF_RETAIN, default=DEFAULT_RETAIN): cv.boolean,
vol.Optional(CONF_STATE_OPEN, default=STATE_OPEN): cv.string,
vol.Optional(CONF_STATE_CLOSED, default=STATE_CLOSED): cv.string,
vol.Optional(CONF_SERVICE_OPEN, default=SERVICE_OPEN): cv.string,
vol.Optional(CONF_SERVICE_CLOSE, default=SERVICE_CLOSE): cv.string
})
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
"""Add MQTT Garage Door."""
value_template = config.get(CONF_VALUE_TEMPLATE)
if value_template is not None:
value_template.hass = hass
add_devices_callback([MqttGarageDoor(
hass,
config[CONF_NAME],
config.get(CONF_STATE_TOPIC),
config[CONF_COMMAND_TOPIC],
config[CONF_QOS],
config[CONF_RETAIN],
config[CONF_STATE_OPEN],
config[CONF_STATE_CLOSED],
config[CONF_SERVICE_OPEN],
config[CONF_SERVICE_CLOSE],
config[CONF_OPTIMISTIC],
value_template)])
# pylint: disable=too-many-arguments, too-many-instance-attributes
class MqttGarageDoor(GarageDoorDevice):
"""Representation of a MQTT garage door."""
def __init__(self, hass, name, state_topic, command_topic, qos, retain,
state_open, state_closed, service_open, service_close,
optimistic, value_template):
"""Initialize the garage door."""
self._hass = hass
self._name = name
self._state_topic = state_topic
self._command_topic = command_topic
self._qos = qos
self._retain = retain
self._state_open = state_open
self._state_closed = state_closed
self._service_open = service_open
self._service_close = service_close
self._optimistic = optimistic or state_topic is None
self._state = False
def message_received(topic, payload, qos):
"""A new MQTT message has been received."""
if value_template is not None:
payload = value_template.render_with_possible_json_value(
payload)
if payload == self._state_open:
self._state = True
self.update_ha_state()
elif payload == self._state_closed:
self._state = False
self.update_ha_state()
if self._state_topic is None:
# Force into optimistic mode.
self._optimistic = True
else:
mqtt.subscribe(hass, self._state_topic, message_received,
self._qos)
@property
def name(self):
"""Return the name of the garage door if any."""
return self._name
@property
def is_opened(self):
"""Return true if door is closed."""
return self._state
@property
def is_closed(self):
"""Return true if door is closed."""
return self._state is False
@property
def assumed_state(self):
"""Return true if we do optimistic updates."""
return self._optimistic
def close_door(self):
"""Close the door."""
mqtt.publish(self.hass, self._command_topic, self._service_close,
self._qos, self._retain)
if self._optimistic:
# Optimistically assume that door has changed state.
self._state = False
self.update_ha_state()
def open_door(self):
"""Open the door."""
mqtt.publish(self.hass, self._command_topic, self._service_open,
self._qos, self._retain)
if self._optimistic:
# Optimistically assume that door has changed state.
self._state = True
self.update_ha_state()

View File

@ -1,110 +0,0 @@
"""
Support for building a Raspberry Pi garage controller in HA.
Instructions for building the controller can be found here
https://github.com/andrewshilliday/garage-door-controller
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/garage_door.rpi_gpio/
"""
import logging
from time import sleep
import voluptuous as vol
from homeassistant.components.garage_door import GarageDoorDevice
import homeassistant.components.rpi_gpio as rpi_gpio
import homeassistant.helpers.config_validation as cv
RELAY_TIME = 'relay_time'
STATE_PULL_MODE = 'state_pull_mode'
DEFAULT_PULL_MODE = 'UP'
DEFAULT_RELAY_TIME = .2
DEPENDENCIES = ['rpi_gpio']
_LOGGER = logging.getLogger(__name__)
_DOORS_SCHEMA = vol.All(
cv.ensure_list,
[
vol.Schema({
'name': str,
'relay_pin': int,
'state_pin': int,
})
]
)
PLATFORM_SCHEMA = vol.Schema({
'platform': str,
vol.Required('doors'): _DOORS_SCHEMA,
vol.Optional(STATE_PULL_MODE, default=DEFAULT_PULL_MODE): cv.string,
vol.Optional(RELAY_TIME, default=DEFAULT_RELAY_TIME): vol.Coerce(int),
})
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the garage door platform."""
relay_time = config.get(RELAY_TIME)
state_pull_mode = config.get(STATE_PULL_MODE)
doors = []
doors_conf = config.get('doors')
for door in doors_conf:
doors.append(RPiGPIOGarageDoor(door['name'], door['relay_pin'],
door['state_pin'],
state_pull_mode,
relay_time))
add_devices(doors)
class RPiGPIOGarageDoor(GarageDoorDevice):
"""Representation of a Raspberry garage door."""
# pylint: disable=too-many-arguments
def __init__(self, name, relay_pin, state_pin,
state_pull_mode, relay_time):
"""Initialize the garage door."""
self._name = name
self._state = False
self._relay_pin = relay_pin
self._state_pin = state_pin
self._state_pull_mode = state_pull_mode
self._relay_time = relay_time
rpi_gpio.setup_output(self._relay_pin)
rpi_gpio.setup_input(self._state_pin, self._state_pull_mode)
rpi_gpio.write_output(self._relay_pin, True)
@property
def unique_id(self):
"""Return the ID of this garage door."""
return "{}.{}".format(self.__class__, self._name)
@property
def name(self):
"""Return the name of the garage door if any."""
return self._name
def update(self):
"""Update the state of the garage door."""
self._state = rpi_gpio.read_input(self._state_pin)
@property
def is_closed(self):
"""Return true if door is closed."""
return self._state
def _trigger(self):
"""Trigger the door."""
rpi_gpio.write_output(self._relay_pin, False)
sleep(self._relay_time)
rpi_gpio.write_output(self._relay_pin, True)
def close_door(self):
"""Close the door."""
if not self.is_closed:
self._trigger()
def open_door(self):
"""Open the door."""
if self.is_closed:
self._trigger()

View File

@ -1,15 +0,0 @@
open:
description: Open all or specified garage door
fields:
entity_id:
description: Name(s) of garage door(s) to open
example: 'garage.main'
close:
description: Close all or a specified garage door
fields:
entity_id:
description: Name(s) of garage door(s) to close
example: 'garage.main'

View File

@ -1,40 +0,0 @@
"""
Support for Wink garage doors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/garage_door.wink/
"""
from homeassistant.components.garage_door import GarageDoorDevice
from homeassistant.components.wink import WinkDevice
DEPENDENCIES = ['wink']
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Wink garage door platform."""
import pywink
add_devices(WinkGarageDoorDevice(door) for door in
pywink.get_garage_doors())
class WinkGarageDoorDevice(WinkDevice, GarageDoorDevice):
"""Representation of a Wink garage door."""
def __init__(self, wink):
"""Initialize the garage door."""
WinkDevice.__init__(self, wink)
@property
def is_closed(self):
"""Return true if door is closed."""
return self.wink.state() == 0
def close_door(self):
"""Close the door."""
self.wink.set_state(0)
def open_door(self):
"""Open the door."""
self.wink.set_state(1)

View File

@ -1,70 +0,0 @@
"""
Support for Zwave garage door components.
For more details about this platform, please refer to the documentation
https://home-assistant.io/components/garagedoor.zwave/
"""
# Because we do not compile openzwave on CI
# pylint: disable=import-error
import logging
from homeassistant.components.garage_door import DOMAIN
from homeassistant.components.zwave import ZWaveDeviceEntity
from homeassistant.components import zwave
from homeassistant.components.garage_door import GarageDoorDevice
COMMAND_CLASS_SWITCH_BINARY = 0x25 # 37
COMMAND_CLASS_BARRIER_OPERATOR = 0x66 # 102
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Find and return Z-Wave garage door device."""
if discovery_info is None or zwave.NETWORK is None:
return
node = zwave.NETWORK.nodes[discovery_info[zwave.const.ATTR_NODE_ID]]
value = node.values[discovery_info[zwave.const.ATTR_VALUE_ID]]
if value.command_class != zwave.const.COMMAND_CLASS_SWITCH_BINARY and \
value.command_class != zwave.const.COMMAND_CLASS_BARRIER_OPERATOR:
return
if value.type != zwave.const.TYPE_BOOL:
return
if value.genre != zwave.const.GENRE_USER:
return
value.set_change_verified(False)
add_devices([ZwaveGarageDoor(value)])
class ZwaveGarageDoor(zwave.ZWaveDeviceEntity, GarageDoorDevice):
"""Representation of an Zwave garage door device."""
def __init__(self, value):
"""Initialize the zwave garage door."""
from openzwave.network import ZWaveNetwork
from pydispatch import dispatcher
ZWaveDeviceEntity.__init__(self, value, DOMAIN)
self._state = value.data
dispatcher.connect(
self.value_changed, ZWaveNetwork.SIGNAL_VALUE_CHANGED)
def value_changed(self, value):
"""Called when a value has changed on the network."""
if self._value.value_id == value.value_id:
self._state = value.data
self.update_ha_state()
_LOGGER.debug("Value changed on network %s", value)
@property
def is_closed(self):
"""Return the current position of Zwave garage door."""
return not self._state
def close_door(self):
"""Close the garage door."""
self._value.data = False
def open_door(self):
"""Open the garage door."""
self._value.data = True

View File

@ -1,500 +0,0 @@
"""
Provides functionality to interact with hvacs.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/hvac/
"""
import logging
import os
from numbers import Number
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.config import load_yaml_config_file
import homeassistant.util as util
from homeassistant.util.temperature import convert as convert_temperature
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa
from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_TEMPERATURE, STATE_ON, STATE_OFF, STATE_UNKNOWN,
TEMP_CELSIUS)
DOMAIN = "hvac"
ENTITY_ID_FORMAT = DOMAIN + ".{}"
SCAN_INTERVAL = 60
SERVICE_SET_AWAY_MODE = "set_away_mode"
SERVICE_SET_AUX_HEAT = "set_aux_heat"
SERVICE_SET_TEMPERATURE = "set_temperature"
SERVICE_SET_FAN_MODE = "set_fan_mode"
SERVICE_SET_OPERATION_MODE = "set_operation_mode"
SERVICE_SET_SWING_MODE = "set_swing_mode"
SERVICE_SET_HUMIDITY = "set_humidity"
STATE_HEAT = "heat"
STATE_COOL = "cool"
STATE_IDLE = "idle"
STATE_AUTO = "auto"
STATE_DRY = "dry"
STATE_FAN_ONLY = "fan_only"
ATTR_CURRENT_TEMPERATURE = "current_temperature"
ATTR_MAX_TEMP = "max_temp"
ATTR_MIN_TEMP = "min_temp"
ATTR_AWAY_MODE = "away_mode"
ATTR_AUX_HEAT = "aux_heat"
ATTR_FAN_MODE = "fan_mode"
ATTR_FAN_LIST = "fan_list"
ATTR_CURRENT_HUMIDITY = "current_humidity"
ATTR_HUMIDITY = "humidity"
ATTR_MAX_HUMIDITY = "max_humidity"
ATTR_MIN_HUMIDITY = "min_humidity"
ATTR_OPERATION_MODE = "operation_mode"
ATTR_OPERATION_LIST = "operation_list"
ATTR_SWING_MODE = "swing_mode"
ATTR_SWING_LIST = "swing_list"
_LOGGER = logging.getLogger(__name__)
def set_away_mode(hass, away_mode, entity_id=None):
"""Turn all or specified hvac away mode on."""
data = {
ATTR_AWAY_MODE: away_mode
}
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_SET_AWAY_MODE, data)
def set_aux_heat(hass, aux_heat, entity_id=None):
"""Turn all or specified hvac auxillary heater on."""
data = {
ATTR_AUX_HEAT: aux_heat
}
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_SET_AUX_HEAT, data)
def set_temperature(hass, temperature, entity_id=None):
"""Set new target temperature."""
data = {ATTR_TEMPERATURE: temperature}
if entity_id is not None:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_SET_TEMPERATURE, data)
def set_humidity(hass, humidity, entity_id=None):
"""Set new target humidity."""
data = {ATTR_HUMIDITY: humidity}
if entity_id is not None:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_SET_HUMIDITY, data)
def set_fan_mode(hass, fan, entity_id=None):
"""Turn all or specified hvac fan mode on."""
data = {ATTR_FAN_MODE: fan}
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_SET_FAN_MODE, data)
def set_operation_mode(hass, operation_mode, entity_id=None):
"""Set new target operation mode."""
data = {ATTR_OPERATION_MODE: operation_mode}
if entity_id is not None:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_SET_OPERATION_MODE, data)
def set_swing_mode(hass, swing_mode, entity_id=None):
"""Set new target swing mode."""
data = {ATTR_SWING_MODE: swing_mode}
if entity_id is not None:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_SET_SWING_MODE, data)
# pylint: disable=too-many-branches
def setup(hass, config):
"""Setup hvacs."""
_LOGGER.warning('This component has been deprecated in favour of'
' the "climate" component and will be removed '
'in the future. Please upgrade.')
component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL)
component.setup(config)
descriptions = load_yaml_config_file(
os.path.join(os.path.dirname(__file__), 'services.yaml'))
def away_mode_set_service(service):
"""Set away mode on target hvacs."""
target_hvacs = component.extract_from_service(service)
away_mode = service.data.get(ATTR_AWAY_MODE)
if away_mode is None:
_LOGGER.error(
"Received call to %s without attribute %s",
SERVICE_SET_AWAY_MODE, ATTR_AWAY_MODE)
return
for hvac in target_hvacs:
if away_mode:
hvac.turn_away_mode_on()
else:
hvac.turn_away_mode_off()
if hvac.should_poll:
hvac.update_ha_state(True)
hass.services.register(
DOMAIN, SERVICE_SET_AWAY_MODE, away_mode_set_service,
descriptions.get(SERVICE_SET_AWAY_MODE))
def aux_heat_set_service(service):
"""Set auxillary heater on target hvacs."""
target_hvacs = component.extract_from_service(service)
aux_heat = service.data.get(ATTR_AUX_HEAT)
if aux_heat is None:
_LOGGER.error(
"Received call to %s without attribute %s",
SERVICE_SET_AUX_HEAT, ATTR_AUX_HEAT)
return
for hvac in target_hvacs:
if aux_heat:
hvac.turn_aux_heat_on()
else:
hvac.turn_aux_heat_off()
if hvac.should_poll:
hvac.update_ha_state(True)
hass.services.register(
DOMAIN, SERVICE_SET_AUX_HEAT, aux_heat_set_service,
descriptions.get(SERVICE_SET_AUX_HEAT))
def temperature_set_service(service):
"""Set temperature on the target hvacs."""
target_hvacs = component.extract_from_service(service)
temperature = util.convert(
service.data.get(ATTR_TEMPERATURE), float)
if temperature is None:
_LOGGER.error(
"Received call to %s without attribute %s",
SERVICE_SET_TEMPERATURE, ATTR_TEMPERATURE)
return
for hvac in target_hvacs:
hvac.set_temperature(convert_temperature(
temperature, hass.config.units.temperature_unit,
hvac.unit_of_measurement))
if hvac.should_poll:
hvac.update_ha_state(True)
hass.services.register(
DOMAIN, SERVICE_SET_TEMPERATURE, temperature_set_service,
descriptions.get(SERVICE_SET_TEMPERATURE))
def humidity_set_service(service):
"""Set humidity on the target hvacs."""
target_hvacs = component.extract_from_service(service)
humidity = service.data.get(ATTR_HUMIDITY)
if humidity is None:
_LOGGER.error(
"Received call to %s without attribute %s",
SERVICE_SET_HUMIDITY, ATTR_HUMIDITY)
return
for hvac in target_hvacs:
hvac.set_humidity(humidity)
if hvac.should_poll:
hvac.update_ha_state(True)
hass.services.register(
DOMAIN, SERVICE_SET_HUMIDITY, humidity_set_service,
descriptions.get(SERVICE_SET_HUMIDITY))
def fan_mode_set_service(service):
"""Set fan mode on target hvacs."""
target_hvacs = component.extract_from_service(service)
fan = service.data.get(ATTR_FAN_MODE)
if fan is None:
_LOGGER.error(
"Received call to %s without attribute %s",
SERVICE_SET_FAN_MODE, ATTR_FAN_MODE)
return
for hvac in target_hvacs:
hvac.set_fan_mode(fan)
if hvac.should_poll:
hvac.update_ha_state(True)
hass.services.register(
DOMAIN, SERVICE_SET_FAN_MODE, fan_mode_set_service,
descriptions.get(SERVICE_SET_FAN_MODE))
def operation_set_service(service):
"""Set operating mode on the target hvacs."""
target_hvacs = component.extract_from_service(service)
operation_mode = service.data.get(ATTR_OPERATION_MODE)
if operation_mode is None:
_LOGGER.error(
"Received call to %s without attribute %s",
SERVICE_SET_OPERATION_MODE, ATTR_OPERATION_MODE)
return
for hvac in target_hvacs:
hvac.set_operation_mode(operation_mode)
if hvac.should_poll:
hvac.update_ha_state(True)
hass.services.register(
DOMAIN, SERVICE_SET_OPERATION_MODE, operation_set_service,
descriptions.get(SERVICE_SET_OPERATION_MODE))
def swing_set_service(service):
"""Set swing mode on the target hvacs."""
target_hvacs = component.extract_from_service(service)
swing_mode = service.data.get(ATTR_SWING_MODE)
if swing_mode is None:
_LOGGER.error(
"Received call to %s without attribute %s",
SERVICE_SET_SWING_MODE, ATTR_SWING_MODE)
return
for hvac in target_hvacs:
hvac.set_swing_mode(swing_mode)
if hvac.should_poll:
hvac.update_ha_state(True)
hass.services.register(
DOMAIN, SERVICE_SET_SWING_MODE, swing_set_service,
descriptions.get(SERVICE_SET_SWING_MODE))
return True
class HvacDevice(Entity):
"""Representation of a hvac."""
# pylint: disable=too-many-public-methods,no-self-use
@property
def state(self):
"""Return the current state."""
return self.current_operation or STATE_UNKNOWN
@property
def state_attributes(self):
"""Return the optional state attributes."""
data = {
ATTR_CURRENT_TEMPERATURE:
self._convert_for_display(self.current_temperature),
ATTR_MIN_TEMP: self._convert_for_display(self.min_temp),
ATTR_MAX_TEMP: self._convert_for_display(self.max_temp),
ATTR_TEMPERATURE:
self._convert_for_display(self.target_temperature),
}
humidity = self.target_humidity
if humidity is not None:
data[ATTR_HUMIDITY] = humidity
data[ATTR_CURRENT_HUMIDITY] = self.current_humidity
data[ATTR_MIN_HUMIDITY] = self.min_humidity
data[ATTR_MAX_HUMIDITY] = self.max_humidity
fan_mode = self.current_fan_mode
if fan_mode is not None:
data[ATTR_FAN_MODE] = fan_mode
data[ATTR_FAN_LIST] = self.fan_list
operation_mode = self.current_operation
if operation_mode is not None:
data[ATTR_OPERATION_MODE] = operation_mode
data[ATTR_OPERATION_LIST] = self.operation_list
swing_mode = self.current_swing_mode
if swing_mode is not None:
data[ATTR_SWING_MODE] = swing_mode
data[ATTR_SWING_LIST] = self.swing_list
is_away = self.is_away_mode_on
if is_away is not None:
data[ATTR_AWAY_MODE] = STATE_ON if is_away else STATE_OFF
is_aux_heat = self.is_aux_heat_on
if is_aux_heat is not None:
data[ATTR_AUX_HEAT] = STATE_ON if is_aux_heat else STATE_OFF
return data
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
raise NotImplementedError
@property
def current_humidity(self):
"""Return the current humidity."""
return None
@property
def target_humidity(self):
"""Return the humidity we try to reach."""
return None
@property
def current_operation(self):
"""Return current operation ie. heat, cool, idle."""
return None
@property
def operation_list(self):
"""List of available operation modes."""
return None
@property
def current_temperature(self):
"""Return the current temperature."""
return None
@property
def target_temperature(self):
"""Return the temperature we try to reach."""
raise NotImplementedError
@property
def is_away_mode_on(self):
"""Return true if away mode is on."""
return None
@property
def is_aux_heat_on(self):
"""Return true if away mode is on."""
return None
@property
def current_fan_mode(self):
"""Return the fan setting."""
return None
@property
def fan_list(self):
"""List of available fan modes."""
return None
@property
def current_swing_mode(self):
"""Return the fan setting."""
return None
@property
def swing_list(self):
"""List of available swing modes."""
return None
def set_temperature(self, temperature):
"""Set new target temperature."""
raise NotImplementedError()
def set_humidity(self, humidity):
"""Set new target humidity."""
raise NotImplementedError()
def set_fan_mode(self, fan):
"""Set new target fan mode."""
raise NotImplementedError()
def set_operation_mode(self, operation_mode):
"""Set new target operation mode."""
raise NotImplementedError()
def set_swing_mode(self, swing_mode):
"""Set new target swing operation."""
raise NotImplementedError()
def turn_away_mode_on(self):
"""Turn away mode on."""
raise NotImplementedError()
def turn_away_mode_off(self):
"""Turn away mode off."""
raise NotImplementedError()
def turn_aux_heat_on(self):
"""Turn auxillary heater on."""
raise NotImplementedError()
def turn_aux_heat_off(self):
"""Turn auxillary heater off."""
raise NotImplementedError()
@property
def min_temp(self):
"""Return the minimum temperature."""
return convert_temperature(19, TEMP_CELSIUS, self.unit_of_measurement)
@property
def max_temp(self):
"""Return the maximum temperature."""
return convert_temperature(30, TEMP_CELSIUS, self.unit_of_measurement)
@property
def min_humidity(self):
"""Return the minimum humidity."""
return 30
@property
def max_humidity(self):
"""Return the maximum humidity."""
return 99
def _convert_for_display(self, temp):
"""Convert temperature into preferred units for display purposes."""
if temp is None or not isinstance(temp, Number):
return temp
value = convert_temperature(temp, self.unit_of_measurement,
self.hass.config.units.temperature_unit)
if self.hass.config.units.temperature_unit is TEMP_CELSIUS:
decimal_count = 1
else:
# Users of fahrenheit generally expect integer units.
decimal_count = 0
return round(value, decimal_count)

View File

@ -1,164 +0,0 @@
"""
Demo platform that offers a fake hvac.
For more details about this platform, please refer to the documentation
https://home-assistant.io/components/demo/
"""
from homeassistant.components.hvac import HvacDevice
from homeassistant.const import TEMP_CELSIUS, TEMP_FAHRENHEIT
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Demo hvacs."""
add_devices([
DemoHvac("HeatPump", 68, TEMP_FAHRENHEIT, None, 77, "Auto Low",
None, None, "Auto", "Heat", None),
DemoHvac("Hvac", 21, TEMP_CELSIUS, True, 22, "On High",
67, 54, "Off", "Cool", False),
])
# pylint: disable=too-many-arguments, too-many-public-methods
class DemoHvac(HvacDevice):
"""Representation of a demo hvac."""
# pylint: disable=too-many-instance-attributes
def __init__(self, name, target_temperature, unit_of_measurement,
away, current_temperature, current_fan_mode,
target_humidity, current_humidity, current_swing_mode,
current_operation, aux):
"""Initialize the hvac."""
self._name = name
self._target_temperature = target_temperature
self._target_humidity = target_humidity
self._unit_of_measurement = unit_of_measurement
self._away = away
self._current_temperature = current_temperature
self._current_humidity = current_humidity
self._current_fan_mode = current_fan_mode
self._current_operation = current_operation
self._aux = aux
self._current_swing_mode = current_swing_mode
self._fan_list = ["On Low", "On High", "Auto Low", "Auto High", "Off"]
self._operation_list = ["Heat", "Cool", "Auto Changeover", "Off"]
self._swing_list = ["Auto", 1, 2, 3, "Off"]
@property
def should_poll(self):
"""Polling not needed for a demo hvac."""
return False
@property
def name(self):
"""Return the name of the hvac."""
return self._name
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
return self._unit_of_measurement
@property
def current_temperature(self):
"""Return the current temperature."""
return self._current_temperature
@property
def target_temperature(self):
"""Return the temperature we try to reach."""
return self._target_temperature
@property
def current_humidity(self):
"""Return the current humidity."""
return self._current_humidity
@property
def target_humidity(self):
"""Return the humidity we try to reach."""
return self._target_humidity
@property
def current_operation(self):
"""Return current operation ie. heat, cool, idle."""
return self._current_operation
@property
def operation_list(self):
"""List of available operation modes."""
return self._operation_list
@property
def is_away_mode_on(self):
"""Return if away mode is on."""
return self._away
@property
def is_aux_heat_on(self):
"""Return true if away mode is on."""
return self._aux
@property
def current_fan_mode(self):
"""Return the fan setting."""
return self._current_fan_mode
@property
def fan_list(self):
"""List of available fan modes."""
return self._fan_list
def set_temperature(self, temperature):
"""Set new target temperature."""
self._target_temperature = temperature
self.update_ha_state()
def set_humidity(self, humidity):
"""Set new target temperature."""
self._target_humidity = humidity
self.update_ha_state()
def set_swing_mode(self, swing_mode):
"""Set new target temperature."""
self._current_swing_mode = swing_mode
self.update_ha_state()
def set_fan_mode(self, fan):
"""Set new target temperature."""
self._current_fan_mode = fan
self.update_ha_state()
def set_operation_mode(self, operation_mode):
"""Set new target temperature."""
self._current_operation = operation_mode
self.update_ha_state()
@property
def current_swing_mode(self):
"""Return the swing setting."""
return self._current_swing_mode
@property
def swing_list(self):
"""List of available swing modes."""
return self._swing_list
def turn_away_mode_on(self):
"""Turn away mode on."""
self._away = True
self.update_ha_state()
def turn_away_mode_off(self):
"""Turn away mode off."""
self._away = False
self.update_ha_state()
def turn_aux_heat_on(self):
"""Turn away auxillary heater on."""
self._aux = True
self.update_ha_state()
def turn_aux_heat_off(self):
"""Turn auxillary heater off."""
self._aux = False
self.update_ha_state()

View File

@ -1,84 +0,0 @@
set_aux_heat:
description: Turn auxillary heater on/off for hvac
fields:
entity_id:
description: Name(s) of entities to change
example: 'hvac.kitchen'
aux_heat:
description: New value of axillary heater
example: true
set_away_mode:
description: Turn away mode on/off for hvac
fields:
entity_id:
description: Name(s) of entities to change
example: 'hvac.kitchen'
away_mode:
description: New value of away mode
example: true
set_temperature:
description: Set target temperature of hvac
fields:
entity_id:
description: Name(s) of entities to change
example: 'hvac.kitchen'
temperature:
description: New target temperature for hvac
example: 25
set_humidity:
description: Set target humidity of hvac
fields:
entity_id:
description: Name(s) of entities to change
example: 'hvac.kitchen'
humidity:
description: New target humidity for hvac
example: 60
set_fan_mode:
description: Set fan operation for hvac
fields:
entity_id:
description: Name(s) of entities to change
example: 'hvac.nest'
fan:
description: New value of fan mode
example: On Low
set_operation_mode:
description: Set operation mode for hvac
fields:
entity_id:
description: Name(s) of entities to change
example: 'hvac.nest'
operation_mode:
description: New value of operation mode
example: Heat
set_swing_mode:
description: Set swing operation for hvac
fields:
entity_id:
description: Name(s) of entities to change
example: 'hvac.nest'
swing_mode:
description: New value of swing mode
example: 1

View File

@ -1,241 +0,0 @@
"""
Support for ZWave HVAC devices.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/hvac.zwave/
"""
# Because we do not compile openzwave on CI
# pylint: disable=import-error
import logging
from homeassistant.components.hvac import DOMAIN
from homeassistant.components.hvac import HvacDevice
from homeassistant.components.zwave import ZWaveDeviceEntity
from homeassistant.components import zwave
from homeassistant.const import (TEMP_FAHRENHEIT, TEMP_CELSIUS)
_LOGGER = logging.getLogger(__name__)
CONF_NAME = 'name'
DEFAULT_NAME = 'ZWave Hvac'
REMOTEC = 0x5254
REMOTEC_ZXT_120 = 0x8377
REMOTEC_ZXT_120_THERMOSTAT = (REMOTEC, REMOTEC_ZXT_120, 0)
WORKAROUND_ZXT_120 = 'zxt_120'
DEVICE_MAPPINGS = {
REMOTEC_ZXT_120_THERMOSTAT: WORKAROUND_ZXT_120
}
ZXT_120_SET_TEMP = {
'Heat': 1,
'Cool': 2,
'Dry Air': 8,
'Auto Changeover': 10
}
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the ZWave Hvac devices."""
if discovery_info is None or zwave.NETWORK is None:
_LOGGER.debug("No discovery_info=%s or no NETWORK=%s",
discovery_info, zwave.NETWORK)
return
node = zwave.NETWORK.nodes[discovery_info[zwave.const.ATTR_NODE_ID]]
value = node.values[discovery_info[zwave.const.ATTR_VALUE_ID]]
value.set_change_verified(False)
add_devices([ZWaveHvac(value)])
_LOGGER.debug("discovery_info=%s and zwave.NETWORK=%s",
discovery_info, zwave.NETWORK)
# pylint: disable=too-many-arguments, abstract-method
class ZWaveHvac(ZWaveDeviceEntity, HvacDevice):
"""Represents a HeatControl hvac."""
# pylint: disable=too-many-public-methods, too-many-instance-attributes
def __init__(self, value):
"""Initialize the zwave hvac."""
from openzwave.network import ZWaveNetwork
from pydispatch import dispatcher
ZWaveDeviceEntity.__init__(self, value, DOMAIN)
self._node = value.node
self._target_temperature = None
self._current_temperature = None
self._current_operation = None
self._operation_list = None
self._current_operation_state = None
self._current_fan_mode = None
self._fan_list = None
self._current_swing_mode = None
self._swing_list = None
self._unit = None
self._zxt_120 = None
self.update_properties()
# register listener
dispatcher.connect(
self.value_changed, ZWaveNetwork.SIGNAL_VALUE_CHANGED)
# Make sure that we have values for the key before converting to int
if (value.node.manufacturer_id.strip() and
value.node.product_id.strip()):
specific_sensor_key = (int(value.node.manufacturer_id, 16),
int(value.node.product_id, 16),
value.index)
if specific_sensor_key in DEVICE_MAPPINGS:
if DEVICE_MAPPINGS[specific_sensor_key] == WORKAROUND_ZXT_120:
_LOGGER.debug("Remotec ZXT-120 Zwave Thermostat as HVAC")
self._zxt_120 = 1
def value_changed(self, value):
"""Called when a value has changed on the network."""
if self._value.value_id == value.value_id or \
self._value.node == value.node:
self.update_properties()
self.update_ha_state()
_LOGGER.debug("Value changed on network %s", value)
def update_properties(self):
"""Callback on data change for the registered node/value pair."""
# Set point
for value in (self._node.get_values(
class_id=zwave.const.COMMAND_CLASS_THERMOSTAT_SETPOINT)
.values()):
if int(value.data) != 0:
self._target_temperature = int(value.data)
# Operation Mode
for value in (self._node.get_values(
class_id=zwave.const.COMMAND_CLASS_THERMOSTAT_MODE)
.values()):
self._current_operation = value.data
self._operation_list = list(value.data_items)
_LOGGER.debug("self._operation_list=%s", self._operation_list)
# Current Temp
for value in (self._node.get_values(
class_id=zwave.const.COMMAND_CLASS_SENSOR_MULTILEVEL)
.values()):
if value.label == 'Temperature':
self._current_temperature = int(value.data)
self._unit = value.units
# Fan Mode
for value in (self._node.get_values(
class_id=zwave.const.COMMAND_CLASS_THERMOSTAT_FAN_MODE)
.values()):
self._current_operation_state = value.data
self._fan_list = list(value.data_items)
_LOGGER.debug("self._fan_list=%s", self._fan_list)
_LOGGER.debug("self._current_operation_state=%s",
self._current_operation_state)
# Swing mode
if self._zxt_120 == 1:
for value in (self._node.get_values(
class_id=zwave.const.COMMAND_CLASS_CONFIGURATION)
.values()):
if value.command_class == 112 and value.index == 33:
self._current_swing_mode = value.data
self._swing_list = list(value.data_items)
_LOGGER.debug("self._swing_list=%s", self._swing_list)
@property
def should_poll(self):
"""No polling on ZWave."""
return False
@property
def current_fan_mode(self):
"""Return the fan speed set."""
return self._current_operation_state
@property
def fan_list(self):
"""List of available fan modes."""
return self._fan_list
@property
def current_swing_mode(self):
"""Return the swing mode set."""
return self._current_swing_mode
@property
def swing_list(self):
"""List of available swing modes."""
return self._swing_list
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
unit = self._unit
if unit == 'C':
return TEMP_CELSIUS
elif unit == 'F':
return TEMP_FAHRENHEIT
else:
_LOGGER.exception("unit_of_measurement=%s is not valid",
unit)
@property
def current_temperature(self):
"""Return the current temperature."""
return self._current_temperature
@property
def current_operation(self):
"""Return the current operation mode."""
return self._current_operation
@property
def operation_list(self):
"""List of available operation modes."""
return self._operation_list
@property
def target_temperature(self):
"""Return the temperature we try to reach."""
return self._target_temperature
def set_temperature(self, temperature):
"""Set new target temperature."""
for value in (self._node.get_values(
class_id=zwave.const.COMMAND_CLASS_THERMOSTAT_SETPOINT)
.values()):
if value.command_class != 67:
continue
if self._zxt_120:
# ZXT-120 does not support get setpoint
self._target_temperature = temperature
if ZXT_120_SET_TEMP.get(self._current_operation) \
!= value.index:
continue
# ZXT-120 responds only to whole int
value.data = int(round(temperature, 0))
else:
value.data = int(temperature)
break
def set_fan_mode(self, fan):
"""Set new target fan mode."""
for value in (self._node.get_values(
class_id=zwave.const.COMMAND_CLASS_THERMOSTAT_FAN_MODE)
.values()):
if value.command_class == 68 and value.index == 0:
value.data = bytes(fan, 'utf-8')
break
def set_operation_mode(self, operation_mode):
"""Set new target operation mode."""
for value in self._node.get_values(
class_id=zwave.const.COMMAND_CLASS_THERMOSTAT_MODE).values():
if value.command_class == 64 and value.index == 0:
value.data = bytes(operation_mode, 'utf-8')
break
def set_swing_mode(self, swing_mode):
"""Set new target swing mode."""
if self._zxt_120 == 1:
for value in self._node.get_values(
class_id=zwave.const.COMMAND_CLASS_CONFIGURATION).values():
if value.command_class == 112 and value.index == 33:
value.data = bytes(swing_mode, 'utf-8')
break

View File

@ -1,174 +0,0 @@
"""
Support for Roller shutters.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/rollershutter/
"""
import os
import logging
import voluptuous as vol
from homeassistant.config import load_yaml_config_file
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa
import homeassistant.helpers.config_validation as cv
from homeassistant.components import group
from homeassistant.const import (
SERVICE_MOVE_UP, SERVICE_MOVE_DOWN, SERVICE_MOVE_POSITION, SERVICE_STOP,
STATE_OPEN, STATE_CLOSED, STATE_UNKNOWN, ATTR_ENTITY_ID)
DOMAIN = 'rollershutter'
SCAN_INTERVAL = 15
GROUP_NAME_ALL_ROLLERSHUTTERS = 'all rollershutters'
ENTITY_ID_ALL_ROLLERSHUTTERS = group.ENTITY_ID_FORMAT.format(
'all_rollershutters')
ENTITY_ID_FORMAT = DOMAIN + '.{}'
_LOGGER = logging.getLogger(__name__)
ATTR_CURRENT_POSITION = 'current_position'
ATTR_POSITION = 'position'
ROLLERSHUTTER_SERVICE_SCHEMA = vol.Schema({
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
})
ROLLERSHUTTER_MOVE_POSITION_SCHEMA = ROLLERSHUTTER_SERVICE_SCHEMA.extend({
vol.Required(ATTR_POSITION):
vol.All(vol.Coerce(int), vol.Range(min=0, max=100)),
})
def is_open(hass, entity_id=None):
"""Return if the roller shutter is open based on the statemachine."""
entity_id = entity_id or ENTITY_ID_ALL_ROLLERSHUTTERS
return hass.states.is_state(entity_id, STATE_OPEN)
def move_up(hass, entity_id=None):
"""Move up all or specified roller shutter."""
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
hass.services.call(DOMAIN, SERVICE_MOVE_UP, data)
def move_down(hass, entity_id=None):
"""Move down all or specified roller shutter."""
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
hass.services.call(DOMAIN, SERVICE_MOVE_DOWN, data)
def move_position(hass, position, entity_id=None):
"""Move to specific position all or specified roller shutter."""
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
data[ATTR_POSITION] = position
hass.services.call(DOMAIN, SERVICE_MOVE_POSITION, data)
def stop(hass, entity_id=None):
"""Stop all or specified roller shutter."""
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
hass.services.call(DOMAIN, SERVICE_STOP, data)
def setup(hass, config):
"""Track states and offer events for roller shutters."""
_LOGGER.warning('This component has been deprecated in favour of the '
'"cover" component and will be removed in the future.'
' Please upgrade.')
component = EntityComponent(
_LOGGER, DOMAIN, hass, SCAN_INTERVAL, GROUP_NAME_ALL_ROLLERSHUTTERS)
component.setup(config)
def handle_rollershutter_service(service):
"""Handle calls to the roller shutter services."""
target_rollershutters = component.extract_from_service(service)
for rollershutter in target_rollershutters:
if service.service == SERVICE_MOVE_UP:
rollershutter.move_up()
elif service.service == SERVICE_MOVE_DOWN:
rollershutter.move_down()
elif service.service == SERVICE_MOVE_POSITION:
rollershutter.move_position(service.data[ATTR_POSITION])
elif service.service == SERVICE_STOP:
rollershutter.stop()
if rollershutter.should_poll:
rollershutter.update_ha_state(True)
descriptions = load_yaml_config_file(
os.path.join(os.path.dirname(__file__), 'services.yaml'))
hass.services.register(DOMAIN, SERVICE_MOVE_UP,
handle_rollershutter_service,
descriptions.get(SERVICE_MOVE_UP),
schema=ROLLERSHUTTER_SERVICE_SCHEMA)
hass.services.register(DOMAIN, SERVICE_MOVE_DOWN,
handle_rollershutter_service,
descriptions.get(SERVICE_MOVE_DOWN),
schema=ROLLERSHUTTER_SERVICE_SCHEMA)
hass.services.register(DOMAIN, SERVICE_MOVE_POSITION,
handle_rollershutter_service,
descriptions.get(SERVICE_MOVE_POSITION),
schema=ROLLERSHUTTER_MOVE_POSITION_SCHEMA)
hass.services.register(DOMAIN, SERVICE_STOP,
handle_rollershutter_service,
descriptions.get(SERVICE_STOP),
schema=ROLLERSHUTTER_SERVICE_SCHEMA)
return True
class RollershutterDevice(Entity):
"""Representation a rollers hutter."""
# pylint: disable=no-self-use
@property
def current_position(self):
"""Return current position of roller shutter.
None is unknown, 0 is closed, 100 is fully open.
"""
raise NotImplementedError()
@property
def state(self):
"""Return the state of the roller shutter."""
current = self.current_position
if current is None:
return STATE_UNKNOWN
return STATE_CLOSED if current == 0 else STATE_OPEN
@property
def state_attributes(self):
"""Return the state attributes."""
current = self.current_position
if current is None:
return None
return {
ATTR_CURRENT_POSITION: current
}
def move_up(self, **kwargs):
"""Move the roller shutter down."""
raise NotImplementedError()
def move_down(self, **kwargs):
"""Move the roller shutter up."""
raise NotImplementedError()
def move_position(self, **kwargs):
"""Move the roller shutter to a specific position."""
raise NotImplementedError()
def stop(self, **kwargs):
"""Stop the roller shutter."""
raise NotImplementedError()

View File

@ -1,125 +0,0 @@
"""
Support for command roller shutters.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/rollershutter.command_line/
"""
import logging
import subprocess
from homeassistant.components.rollershutter import RollershutterDevice
from homeassistant.const import CONF_VALUE_TEMPLATE
from homeassistant.helpers.template import Template
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
"""Setup roller shutter controlled by shell commands."""
rollershutters = config.get('rollershutters', {})
devices = []
for dev_name, properties in rollershutters.items():
value_template = properties.get(CONF_VALUE_TEMPLATE)
if value_template is not None:
value_template = Template(value_template, hass)
devices.append(
CommandRollershutter(
hass,
properties.get('name', dev_name),
properties.get('upcmd', 'true'),
properties.get('downcmd', 'true'),
properties.get('stopcmd', 'true'),
properties.get('statecmd', False),
value_template))
add_devices_callback(devices)
# pylint: disable=abstract-method
# pylint: disable=too-many-arguments, too-many-instance-attributes
class CommandRollershutter(RollershutterDevice):
"""Representation a command line roller shutter."""
# pylint: disable=too-many-arguments
def __init__(self, hass, name, command_up, command_down, command_stop,
command_state, value_template):
"""Initialize the roller shutter."""
self._hass = hass
self._name = name
self._state = None
self._command_up = command_up
self._command_down = command_down
self._command_stop = command_stop
self._command_state = command_state
self._value_template = value_template
@staticmethod
def _move_rollershutter(command):
"""Execute the actual commands."""
_LOGGER.info('Running command: %s', command)
success = (subprocess.call(command, shell=True) == 0)
if not success:
_LOGGER.error('Command failed: %s', command)
return success
@staticmethod
def _query_state_value(command):
"""Execute state command for return value."""
_LOGGER.info('Running state command: %s', command)
try:
return_value = subprocess.check_output(command, shell=True)
return return_value.strip().decode('utf-8')
except subprocess.CalledProcessError:
_LOGGER.error('Command failed: %s', command)
@property
def should_poll(self):
"""Only poll if we have state command."""
return self._command_state is not None
@property
def name(self):
"""Return the name of the roller shutter."""
return self._name
@property
def current_position(self):
"""Return current position of roller shutter.
None is unknown, 0 is closed, 100 is fully open.
"""
return self._state
def _query_state(self):
"""Query for the state."""
if not self._command_state:
_LOGGER.error('No state command specified')
return
return self._query_state_value(self._command_state)
def update(self):
"""Update device state."""
if self._command_state:
payload = str(self._query_state())
if self._value_template:
payload = self._value_template.render_with_possible_json_value(
payload)
self._state = int(payload)
def move_up(self, **kwargs):
"""Move the roller shutter up."""
self._move_rollershutter(self._command_up)
def move_down(self, **kwargs):
"""Move the roller shutter down."""
self._move_rollershutter(self._command_down)
def stop(self, **kwargs):
"""Stop the device."""
self._move_rollershutter(self._command_stop)

View File

@ -1,92 +0,0 @@
"""
Demo platform for the rollor shutter component.
For more details about this platform, please refer to the documentation
https://home-assistant.io/components/demo/
"""
from homeassistant.components.rollershutter import RollershutterDevice
from homeassistant.helpers.event import track_utc_time_change
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Demo roller shutters."""
add_devices([
DemoRollershutter(hass, 'Kitchen Window', 0),
DemoRollershutter(hass, 'Living Room Window', 100),
])
class DemoRollershutter(RollershutterDevice):
"""Representation of a demo roller shutter."""
# pylint: disable=no-self-use
def __init__(self, hass, name, position):
"""Initialize the roller shutter."""
self.hass = hass
self._name = name
self._position = position
self._moving_up = True
self._unsub_listener = None
@property
def name(self):
"""Return the name of the roller shutter."""
return self._name
@property
def should_poll(self):
"""No polling needed for a demo roller shutter."""
return False
@property
def current_position(self):
"""Return the current position of the roller shutter."""
return self._position
def move_up(self, **kwargs):
"""Move the roller shutter down."""
if self._position == 0:
return
self._listen()
self._moving_up = True
def move_down(self, **kwargs):
"""Move the roller shutter up."""
if self._position == 100:
return
self._listen()
self._moving_up = False
def move_position(self, position, **kwargs):
"""Move the roller shutter to a specific position."""
if self._position == position:
return
self._listen()
self._moving_up = position < self._position
def stop(self, **kwargs):
"""Stop the roller shutter."""
if self._unsub_listener is not None:
self._unsub_listener()
self._unsub_listener = None
def _listen(self):
"""Listen for changes."""
if self._unsub_listener is None:
self._unsub_listener = track_utc_time_change(self.hass,
self._time_changed)
def _time_changed(self, now):
"""Track time changes."""
if self._moving_up:
self._position -= 10
else:
self._position += 10
if self._position % 100 == 0:
self.stop()
self.update_ha_state()

View File

@ -1,123 +0,0 @@
"""
Support for MQTT roller shutters.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/rollershutter.mqtt/
"""
import logging
import voluptuous as vol
import homeassistant.components.mqtt as mqtt
from homeassistant.components.rollershutter import RollershutterDevice
from homeassistant.const import CONF_NAME, CONF_VALUE_TEMPLATE
from homeassistant.components.mqtt import (
CONF_STATE_TOPIC, CONF_COMMAND_TOPIC, CONF_QOS)
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['mqtt']
CONF_PAYLOAD_UP = 'payload_up'
CONF_PAYLOAD_DOWN = 'payload_down'
CONF_PAYLOAD_STOP = 'payload_stop'
DEFAULT_NAME = "MQTT Rollershutter"
DEFAULT_PAYLOAD_UP = "UP"
DEFAULT_PAYLOAD_DOWN = "DOWN"
DEFAULT_PAYLOAD_STOP = "STOP"
PLATFORM_SCHEMA = mqtt.MQTT_RW_PLATFORM_SCHEMA.extend({
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_PAYLOAD_UP, default=DEFAULT_PAYLOAD_UP): cv.string,
vol.Optional(CONF_PAYLOAD_DOWN, default=DEFAULT_PAYLOAD_DOWN): cv.string,
vol.Optional(CONF_PAYLOAD_STOP, default=DEFAULT_PAYLOAD_STOP): cv.string,
})
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
"""Add MQTT Rollershutter."""
value_template = config.get(CONF_VALUE_TEMPLATE)
if value_template is not None:
value_template.hass = hass
add_devices_callback([MqttRollershutter(
hass,
config[CONF_NAME],
config.get(CONF_STATE_TOPIC),
config[CONF_COMMAND_TOPIC],
config[CONF_QOS],
config[CONF_PAYLOAD_UP],
config[CONF_PAYLOAD_DOWN],
config[CONF_PAYLOAD_STOP],
value_template,
)])
# pylint: disable=abstract-method
# pylint: disable=too-many-arguments, too-many-instance-attributes
class MqttRollershutter(RollershutterDevice):
"""Representation of a roller shutter that can be controlled using MQTT."""
def __init__(self, hass, name, state_topic, command_topic, qos,
payload_up, payload_down, payload_stop, value_template):
"""Initialize the roller shutter."""
self._state = None
self._hass = hass
self._name = name
self._state_topic = state_topic
self._command_topic = command_topic
self._qos = qos
self._payload_up = payload_up
self._payload_down = payload_down
self._payload_stop = payload_stop
if self._state_topic is None:
return
def message_received(topic, payload, qos):
"""A new MQTT message has been received."""
if value_template is not None:
payload = value_template.render_with_possible_json_value(
payload)
if payload.isnumeric() and 0 <= int(payload) <= 100:
self._state = int(payload)
self.update_ha_state()
else:
_LOGGER.warning(
"Payload is expected to be an integer between 0 and 100")
mqtt.subscribe(hass, self._state_topic, message_received, self._qos)
@property
def should_poll(self):
"""No polling needed."""
return False
@property
def name(self):
"""Return the name of the roller shutter."""
return self._name
@property
def current_position(self):
"""Return current position of roller shutter.
None is unknown, 0 is closed, 100 is fully open.
"""
return self._state
def move_up(self, **kwargs):
"""Move the roller shutter up."""
mqtt.publish(self.hass, self._command_topic, self._payload_up,
self._qos)
def move_down(self, **kwargs):
"""Move the roller shutter down."""
mqtt.publish(self.hass, self._command_topic, self._payload_down,
self._qos)
def stop(self, **kwargs):
"""Stop the device."""
mqtt.publish(self.hass, self._command_topic, self._payload_stop,
self._qos)

View File

@ -1,67 +0,0 @@
"""
Support for RFXtrx roller shutter components.
For more details about this platform, please refer to the documentation
https://home-assistant.io/components/rollershutter.rfxtrx/
"""
import homeassistant.components.rfxtrx as rfxtrx
from homeassistant.components.rollershutter import RollershutterDevice
DEPENDENCIES = ['rfxtrx']
PLATFORM_SCHEMA = rfxtrx.DEFAULT_SCHEMA
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
"""Setup the Demo roller shutters."""
import RFXtrx as rfxtrxmod
# Add rollershutter from config file
rollershutters = rfxtrx.get_devices_from_config(config,
RfxtrxRollershutter)
add_devices_callback(rollershutters)
def rollershutter_update(event):
"""Callback for roller shutter updates from the RFXtrx gateway."""
if not isinstance(event.device, rfxtrxmod.LightingDevice) or \
event.device.known_to_be_dimmable or \
not event.device.known_to_be_rollershutter:
return
new_device = rfxtrx.get_new_device(event, config, RfxtrxRollershutter)
if new_device:
add_devices_callback([new_device])
rfxtrx.apply_received_command(event)
# Subscribe to main rfxtrx events
if rollershutter_update not in rfxtrx.RECEIVED_EVT_SUBSCRIBERS:
rfxtrx.RECEIVED_EVT_SUBSCRIBERS.append(rollershutter_update)
# pylint: disable=abstract-method
class RfxtrxRollershutter(rfxtrx.RfxtrxDevice, RollershutterDevice):
"""Representation of an rfxtrx roller shutter."""
@property
def should_poll(self):
"""No polling available in rfxtrx roller shutter."""
return False
@property
def current_position(self):
"""No position available in rfxtrx roller shutter."""
return None
def move_up(self, **kwargs):
"""Move the roller shutter up."""
self._send_command("roll_up")
def move_down(self, **kwargs):
"""Move the roller shutter down."""
self._send_command("roll_down")
def stop(self, **kwargs):
"""Stop the roller shutter."""
self._send_command("stop_roll")

View File

@ -1,98 +0,0 @@
"""
Allow to configure a SCSGate roller shutter.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/rollershutter.scsgate/
"""
import logging
import homeassistant.components.scsgate as scsgate
from homeassistant.components.rollershutter import RollershutterDevice
DEPENDENCIES = ['scsgate']
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
"""Setup the SCSGate roller shutter."""
devices = config.get('devices')
rollershutters = []
logger = logging.getLogger(__name__)
if devices:
for _, entity_info in devices.items():
if entity_info['scs_id'] in scsgate.SCSGATE.devices:
continue
logger.info("Adding %s scsgate.rollershutter", entity_info['name'])
name = entity_info['name']
scs_id = entity_info['scs_id']
rollershutter = SCSGateRollerShutter(
name=name,
scs_id=scs_id,
logger=logger)
scsgate.SCSGATE.add_device(rollershutter)
rollershutters.append(rollershutter)
add_devices_callback(rollershutters)
# pylint: disable=abstract-method
# pylint: disable=too-many-arguments, too-many-instance-attributes
class SCSGateRollerShutter(RollershutterDevice):
"""Representation of SCSGate rollershutter."""
def __init__(self, scs_id, name, logger):
"""Initialize the roller shutter."""
self._scs_id = scs_id
self._name = name
self._logger = logger
@property
def scs_id(self):
"""Return the SCSGate ID."""
return self._scs_id
@property
def should_poll(self):
"""No polling needed."""
return False
@property
def name(self):
"""Return the name of the roller shutter."""
return self._name
@property
def current_position(self):
"""Return current position of roller shutter.
None is unknown, 0 is closed, 100 is fully open.
"""
return None
def move_up(self, **kwargs):
"""Move the roller shutter up."""
from scsgate.tasks import RaiseRollerShutterTask
scsgate.SCSGATE.append_task(
RaiseRollerShutterTask(target=self._scs_id))
def move_down(self, **kwargs):
"""Move the rollers hutter down."""
from scsgate.tasks import LowerRollerShutterTask
scsgate.SCSGATE.append_task(
LowerRollerShutterTask(target=self._scs_id))
def stop(self, **kwargs):
"""Stop the device."""
from scsgate.tasks import HaltRollerShutterTask
scsgate.SCSGATE.append_task(HaltRollerShutterTask(target=self._scs_id))
def process_event(self, message):
"""Handle a SCSGate message related with this roller shutter."""
self._logger.debug(
"Rollershutter %s, got message %s",
self._scs_id, message.toggled)

View File

@ -1,31 +0,0 @@
move_up:
description: Move up all or specified roller shutter
fields:
entity_id:
description: Name(s) of roller shutter(s) to move up
example: 'rollershutter.living_room'
move_down:
description: Move down all or specified roller shutter
fields:
entity_id:
description: Name(s) of roller shutter(s) to move down
example: 'rollershutter.living_room'
move_position:
description: Move to specific position all or specified roller shutter
fields:
position:
description: Position of the rollershutter (0 to 100)
example: 30
stop:
description: Stop all or specified roller shutter
fields:
entity_id:
description: Name(s) of roller shutter(s) to stop
example: 'rollershutter.living_room'

View File

@ -1,61 +0,0 @@
"""
Support for Wink Shades.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/rollershutter.wink/
"""
from homeassistant.components.rollershutter import RollershutterDevice
from homeassistant.components.wink import WinkDevice
DEPENDENCIES = ['wink']
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Wink rollershutter platform."""
import pywink
add_devices(WinkRollershutterDevice(shade) for shade in
pywink.get_shades())
# pylint: disable=abstract-method
class WinkRollershutterDevice(WinkDevice, RollershutterDevice):
"""Representation of a Wink rollershutter (shades)."""
def __init__(self, wink):
"""Initialize the rollershutter."""
WinkDevice.__init__(self, wink)
@property
def should_poll(self):
"""Wink Shades don't track their position."""
return False
def move_down(self):
"""Close the shade."""
self.wink.set_state(0)
def move_up(self):
"""Open the shade."""
self.wink.set_state(1)
@property
def current_position(self):
"""Return current position of roller shutter.
Wink reports blind shade positions as 0 or 1.
home-assistant expects:
None is unknown, 0 is closed, 100 is fully open.
"""
state = self.wink.state()
if state == 0:
return 0
elif state == 1:
return 100
else:
return None
def stop(self):
"""Can't stop Wink rollershutter due to API."""
pass

View File

@ -1,139 +0,0 @@
"""
Support for Zwave roller shutter components.
For more details about this platform, please refer to the documentation
https://home-assistant.io/components/rollershutter.zwave/
"""
# Because we do not compile openzwave on CI
# pylint: disable=import-error
import logging
from homeassistant.components.rollershutter import DOMAIN
from homeassistant.components.zwave import ZWaveDeviceEntity
from homeassistant.components import zwave
from homeassistant.components.rollershutter import RollershutterDevice
SOMFY = 0x47
SOMFY_ZRTSI = 0x5a52
SOMFY_ZRTSI_CONTROLLER = (SOMFY, SOMFY_ZRTSI)
WORKAROUND = 'workaround'
DEVICE_MAPPINGS = {
SOMFY_ZRTSI_CONTROLLER: WORKAROUND
}
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Find and return Z-Wave roller shutters."""
if discovery_info is None or zwave.NETWORK is None:
return
node = zwave.NETWORK.nodes[discovery_info[zwave.const.ATTR_NODE_ID]]
value = node.values[discovery_info[zwave.const.ATTR_VALUE_ID]]
if value.command_class != zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL:
return
if value.index != 0:
return
value.set_change_verified(False)
add_devices([ZwaveRollershutter(value)])
class ZwaveRollershutter(zwave.ZWaveDeviceEntity, RollershutterDevice):
"""Representation of an Zwave roller shutter."""
def __init__(self, value):
"""Initialize the zwave rollershutter."""
import libopenzwave
from openzwave.network import ZWaveNetwork
from pydispatch import dispatcher
ZWaveDeviceEntity.__init__(self, value, DOMAIN)
self._lozwmgr = libopenzwave.PyManager()
self._lozwmgr.create()
self._node = value.node
self._current_position = None
self._workaround = None
dispatcher.connect(
self.value_changed, ZWaveNetwork.SIGNAL_VALUE_CHANGED)
if (value.node.manufacturer_id.strip() and
value.node.product_id.strip()):
specific_sensor_key = (int(value.node.manufacturer_id, 16),
int(value.node.product_type, 16))
if specific_sensor_key in DEVICE_MAPPINGS:
if DEVICE_MAPPINGS[specific_sensor_key] == WORKAROUND:
_LOGGER.debug("Controller without positioning feedback")
self._workaround = 1
def value_changed(self, value):
"""Called when a value has changed on the network."""
if self._value.value_id == value.value_id or \
self._value.node == value.node:
self.update_properties()
self.update_ha_state()
_LOGGER.debug("Value changed on network %s", value)
def update_properties(self):
"""Callback on data change for the registered node/value pair."""
# Position value
for value in self._node.get_values(
class_id=zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL).values():
if value.command_class == \
zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL and \
value.label == 'Level':
self._current_position = value.data
@property
def current_position(self):
"""Return the current position of Zwave roller shutter."""
if not self._workaround:
if self._current_position is not None:
if self._current_position <= 5:
return 100
elif self._current_position >= 95:
return 0
else:
return 100 - self._current_position
def move_up(self, **kwargs):
"""Move the roller shutter up."""
for value in (self._node.get_values(
class_id=zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL)
.values()):
if value.command_class == \
zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL and value.label == \
'Open' or value.command_class == \
zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL and value.label == \
'Down':
self._lozwmgr.pressButton(value.value_id)
break
def move_down(self, **kwargs):
"""Move the roller shutter down."""
for value in self._node.get_values(
class_id=zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL).values():
if value.command_class == \
zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL and value.label == \
'Up' or value.command_class == \
zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL and value.label == \
'Close':
self._lozwmgr.pressButton(value.value_id)
break
def move_position(self, position, **kwargs):
"""Move the roller shutter to a specific position."""
self._node.set_dimmer(self._value.value_id, 100 - position)
def stop(self, **kwargs):
"""Stop the roller shutter."""
for value in self._node.get_values(
class_id=zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL).values():
if value.command_class == \
zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL and value.label == \
'Open' or value.command_class == \
zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL and value.label == \
'Down':
self._lozwmgr.releaseButton(value.value_id)
break

View File

@ -1,330 +0,0 @@
"""
Provides functionality to interact with thermostats.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/thermostat/
"""
import logging
import os
from numbers import Number
import voluptuous as vol
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.config import load_yaml_config_file
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa
import homeassistant.helpers.config_validation as cv
from homeassistant.util.temperature import convert
from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_TEMPERATURE, STATE_ON, STATE_OFF, STATE_UNKNOWN,
TEMP_CELSIUS)
DOMAIN = "thermostat"
ENTITY_ID_FORMAT = DOMAIN + ".{}"
SCAN_INTERVAL = 60
SERVICE_SET_AWAY_MODE = "set_away_mode"
SERVICE_SET_TEMPERATURE = "set_temperature"
SERVICE_SET_FAN_MODE = "set_fan_mode"
SERVICE_SET_HVAC_MODE = "set_hvac_mode"
STATE_HEAT = "heat"
STATE_COOL = "cool"
STATE_IDLE = "idle"
STATE_AUTO = "auto"
ATTR_CURRENT_TEMPERATURE = "current_temperature"
ATTR_AWAY_MODE = "away_mode"
ATTR_FAN = "fan"
ATTR_HVAC_MODE = "hvac_mode"
ATTR_MAX_TEMP = "max_temp"
ATTR_MIN_TEMP = "min_temp"
ATTR_TEMPERATURE_LOW = "target_temp_low"
ATTR_TEMPERATURE_HIGH = "target_temp_high"
ATTR_OPERATION = "current_operation"
_LOGGER = logging.getLogger(__name__)
SET_AWAY_MODE_SCHEMA = vol.Schema({
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
vol.Required(ATTR_AWAY_MODE): cv.boolean,
})
SET_TEMPERATURE_SCHEMA = vol.Schema({
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
vol.Required(ATTR_TEMPERATURE): vol.Coerce(float),
})
SET_FAN_MODE_SCHEMA = vol.Schema({
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
vol.Required(ATTR_FAN): cv.boolean,
})
SET_HVAC_MODE_SCHEMA = vol.Schema({
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
vol.Required(ATTR_HVAC_MODE): cv.string,
})
def set_away_mode(hass, away_mode, entity_id=None):
"""Turn all or specified thermostat away mode on."""
data = {
ATTR_AWAY_MODE: away_mode
}
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_SET_AWAY_MODE, data)
def set_temperature(hass, temperature, entity_id=None):
"""Set new target temperature."""
data = {ATTR_TEMPERATURE: temperature}
if entity_id is not None:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_SET_TEMPERATURE, data)
def set_fan_mode(hass, fan_mode, entity_id=None):
"""Turn all or specified thermostat fan mode on."""
data = {
ATTR_FAN: fan_mode
}
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_SET_FAN_MODE, data)
def set_hvac_mode(hass, hvac_mode, entity_id=None):
"""Set specified thermostat hvac mode."""
data = {
ATTR_HVAC_MODE: hvac_mode
}
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_SET_HVAC_MODE, data)
# pylint: disable=too-many-branches
def setup(hass, config):
"""Setup thermostats."""
_LOGGER.warning('This component has been deprecated in favour of'
' the "climate" component and will be removed '
'in the future. Please upgrade.')
component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL)
component.setup(config)
descriptions = load_yaml_config_file(
os.path.join(os.path.dirname(__file__), 'services.yaml'))
def away_mode_set_service(service):
"""Set away mode on target thermostats."""
target_thermostats = component.extract_from_service(service)
away_mode = service.data[ATTR_AWAY_MODE]
for thermostat in target_thermostats:
if away_mode:
thermostat.turn_away_mode_on()
else:
thermostat.turn_away_mode_off()
thermostat.update_ha_state(True)
hass.services.register(
DOMAIN, SERVICE_SET_AWAY_MODE, away_mode_set_service,
descriptions.get(SERVICE_SET_AWAY_MODE),
schema=SET_AWAY_MODE_SCHEMA)
def temperature_set_service(service):
"""Set temperature on the target thermostats."""
target_thermostats = component.extract_from_service(service)
temperature = service.data[ATTR_TEMPERATURE]
for thermostat in target_thermostats:
converted_temperature = convert(
temperature, hass.config.units.temperature_unit,
thermostat.unit_of_measurement)
thermostat.set_temperature(converted_temperature)
thermostat.update_ha_state(True)
hass.services.register(
DOMAIN, SERVICE_SET_TEMPERATURE, temperature_set_service,
descriptions.get(SERVICE_SET_TEMPERATURE),
schema=SET_TEMPERATURE_SCHEMA)
def fan_mode_set_service(service):
"""Set fan mode on target thermostats."""
target_thermostats = component.extract_from_service(service)
fan_mode = service.data[ATTR_FAN]
for thermostat in target_thermostats:
if fan_mode:
thermostat.turn_fan_on()
else:
thermostat.turn_fan_off()
thermostat.update_ha_state(True)
hass.services.register(
DOMAIN, SERVICE_SET_FAN_MODE, fan_mode_set_service,
descriptions.get(SERVICE_SET_FAN_MODE),
schema=SET_FAN_MODE_SCHEMA)
def hvac_mode_set_service(service):
"""Set hvac mode on target thermostats."""
target_thermostats = component.extract_from_service(service)
hvac_mode = service.data[ATTR_HVAC_MODE]
for thermostat in target_thermostats:
thermostat.set_hvac_mode(hvac_mode)
thermostat.update_ha_state(True)
hass.services.register(
DOMAIN, SERVICE_SET_HVAC_MODE, hvac_mode_set_service,
descriptions.get(SERVICE_SET_HVAC_MODE),
schema=SET_HVAC_MODE_SCHEMA)
return True
class ThermostatDevice(Entity):
"""Representation of a thermostat."""
# pylint: disable=no-self-use
@property
def state(self):
"""Return the current state."""
return self.target_temperature or STATE_UNKNOWN
@property
def state_attributes(self):
"""Return the optional state attributes."""
data = {
ATTR_CURRENT_TEMPERATURE:
self._convert_for_display(self.current_temperature),
ATTR_MIN_TEMP: self._convert_for_display(self.min_temp),
ATTR_MAX_TEMP: self._convert_for_display(self.max_temp),
ATTR_TEMPERATURE:
self._convert_for_display(self.target_temperature),
ATTR_TEMPERATURE_LOW:
self._convert_for_display(self.target_temperature_low),
ATTR_TEMPERATURE_HIGH:
self._convert_for_display(self.target_temperature_high),
}
operation = self.operation
if operation is not None:
data[ATTR_OPERATION] = operation
is_away = self.is_away_mode_on
if is_away is not None:
data[ATTR_AWAY_MODE] = STATE_ON if is_away else STATE_OFF
is_fan_on = self.is_fan_on
if is_fan_on is not None:
data[ATTR_FAN] = STATE_ON if is_fan_on else STATE_OFF
return data
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
raise NotImplementedError
@property
def current_temperature(self):
"""Return the current temperature."""
raise NotImplementedError
@property
def operation(self):
"""Return current operation ie. heat, cool, idle."""
return None
@property
def target_temperature(self):
"""Return the temperature we try to reach."""
raise NotImplementedError
@property
def target_temperature_low(self):
"""Return the lower bound temperature we try to reach."""
return self.target_temperature
@property
def target_temperature_high(self):
"""Return the upper bound temperature we try to reach."""
return self.target_temperature
@property
def is_away_mode_on(self):
"""Return true if away mode is on."""
return None
@property
def is_fan_on(self):
"""Return true if the fan is on."""
return None
def set_temperature(self, temperature):
"""Set new target temperature."""
raise NotImplementedError()
def set_hvac_mode(self, hvac_mode):
"""Set hvac mode."""
raise NotImplementedError()
def turn_away_mode_on(self):
"""Turn away mode on."""
raise NotImplementedError()
def turn_away_mode_off(self):
"""Turn away mode off."""
raise NotImplementedError()
def turn_fan_on(self):
"""Turn fan on."""
raise NotImplementedError()
def turn_fan_off(self):
"""Turn fan off."""
raise NotImplementedError()
@property
def min_temp(self):
"""Return the minimum temperature."""
return convert(7, TEMP_CELSIUS, self.unit_of_measurement)
@property
def max_temp(self):
"""Return the maximum temperature."""
return convert(35, TEMP_CELSIUS, self.unit_of_measurement)
def _convert_for_display(self, temp):
"""Convert temperature into preferred units for display purposes."""
if temp is None or not isinstance(temp, Number):
return temp
value = self.hass.config.units.temperature(temp,
self.unit_of_measurement)
if self.hass.config.units.is_metric:
decimal_count = 1
else:
# Users of fahrenheit generally expect integer units.
decimal_count = 0
return round(value, decimal_count)

View File

@ -1,86 +0,0 @@
"""
Demo platform that offers a fake thermostat.
For more details about this platform, please refer to the documentation
https://home-assistant.io/components/demo/
"""
from homeassistant.components.thermostat import ThermostatDevice
from homeassistant.const import TEMP_CELSIUS, TEMP_FAHRENHEIT
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Demo thermostats."""
add_devices([
DemoThermostat("Nest", 21, TEMP_CELSIUS, False, 19, False),
DemoThermostat("Thermostat", 68, TEMP_FAHRENHEIT, True, 77, True),
])
# pylint: disable=too-many-arguments, abstract-method
class DemoThermostat(ThermostatDevice):
"""Representation of a demo thermostat."""
def __init__(self, name, target_temperature, unit_of_measurement,
away, current_temperature, is_fan_on):
"""Initialize the thermostat."""
self._name = name
self._target_temperature = target_temperature
self._unit_of_measurement = unit_of_measurement
self._away = away
self._current_temperature = current_temperature
self._is_fan_on = is_fan_on
@property
def should_poll(self):
"""No polling needed for a demo thermostat."""
return False
@property
def name(self):
"""Return the name of the thermostat."""
return self._name
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
return self._unit_of_measurement
@property
def current_temperature(self):
"""Return the current temperature."""
return self._current_temperature
@property
def target_temperature(self):
"""Return the temperature we try to reach."""
return self._target_temperature
@property
def is_away_mode_on(self):
"""Return if away mode is on."""
return self._away
@property
def is_fan_on(self):
"""Return true if the fan is on."""
return self._is_fan_on
def set_temperature(self, temperature):
"""Set new target temperature."""
self._target_temperature = temperature
def turn_away_mode_on(self):
"""Turn away mode on."""
self._away = True
def turn_away_mode_off(self):
"""Turn away mode off."""
self._away = False
def turn_fan_on(self):
"""Turn fan on."""
self._is_fan_on = True
def turn_fan_off(self):
"""Turn fan off."""
self._is_fan_on = False

View File

@ -1,246 +0,0 @@
"""
Platform for Ecobee Thermostats.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/thermostat.ecobee/
"""
import logging
from os import path
import voluptuous as vol
from homeassistant.components import ecobee
from homeassistant.components.thermostat import (
DOMAIN, STATE_COOL, STATE_HEAT, STATE_IDLE, ThermostatDevice)
from homeassistant.const import (
ATTR_ENTITY_ID, STATE_OFF, STATE_ON, TEMP_FAHRENHEIT)
from homeassistant.config import load_yaml_config_file
import homeassistant.helpers.config_validation as cv
DEPENDENCIES = ['ecobee']
_LOGGER = logging.getLogger(__name__)
ECOBEE_CONFIG_FILE = 'ecobee.conf'
_CONFIGURING = {}
ATTR_FAN_MIN_ON_TIME = "fan_min_on_time"
SERVICE_SET_FAN_MIN_ON_TIME = "ecobee_set_fan_min_on_time"
SET_FAN_MIN_ON_TIME_SCHEMA = vol.Schema({
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
vol.Required(ATTR_FAN_MIN_ON_TIME): vol.Coerce(int),
})
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Ecobee Thermostat Platform."""
if discovery_info is None:
return
data = ecobee.NETWORK
hold_temp = discovery_info['hold_temp']
_LOGGER.info(
"Loading ecobee thermostat component with hold_temp set to %s",
hold_temp)
devices = [Thermostat(data, index, hold_temp)
for index in range(len(data.ecobee.thermostats))]
add_devices(devices)
def fan_min_on_time_set_service(service):
"""Set the minimum fan on time on the target thermostats."""
entity_id = service.data.get('entity_id')
if entity_id:
target_thermostats = [device for device in devices
if device.entity_id == entity_id]
else:
target_thermostats = devices
fan_min_on_time = service.data[ATTR_FAN_MIN_ON_TIME]
for thermostat in target_thermostats:
thermostat.set_fan_min_on_time(str(fan_min_on_time))
thermostat.update_ha_state(True)
descriptions = load_yaml_config_file(
path.join(path.dirname(__file__), 'services.yaml'))
hass.services.register(
DOMAIN, SERVICE_SET_FAN_MIN_ON_TIME, fan_min_on_time_set_service,
descriptions.get(SERVICE_SET_FAN_MIN_ON_TIME),
schema=SET_FAN_MIN_ON_TIME_SCHEMA)
# pylint: disable=too-many-public-methods, abstract-method
class Thermostat(ThermostatDevice):
"""A thermostat class for Ecobee."""
def __init__(self, data, thermostat_index, hold_temp):
"""Initialize the thermostat."""
self.data = data
self.thermostat_index = thermostat_index
self.thermostat = self.data.ecobee.get_thermostat(
self.thermostat_index)
self._name = self.thermostat['name']
self.hold_temp = hold_temp
def update(self):
"""Get the latest state from the thermostat."""
self.data.update()
self.thermostat = self.data.ecobee.get_thermostat(
self.thermostat_index)
@property
def name(self):
"""Return the name of the Ecobee Thermostat."""
return self.thermostat['name']
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
return TEMP_FAHRENHEIT
@property
def current_temperature(self):
"""Return the current temperature."""
return self.thermostat['runtime']['actualTemperature'] / 10
@property
def target_temperature(self):
"""Return the temperature we try to reach."""
if self.hvac_mode == 'heat' or self.hvac_mode == 'auxHeatOnly':
return self.target_temperature_low
elif self.hvac_mode == 'cool':
return self.target_temperature_high
else:
return (self.target_temperature_low +
self.target_temperature_high) / 2
@property
def target_temperature_low(self):
"""Return the lower bound temperature we try to reach."""
return int(self.thermostat['runtime']['desiredHeat'] / 10)
@property
def target_temperature_high(self):
"""Return the upper bound temperature we try to reach."""
return int(self.thermostat['runtime']['desiredCool'] / 10)
@property
def humidity(self):
"""Return the current humidity."""
return self.thermostat['runtime']['actualHumidity']
@property
def desired_fan_mode(self):
"""Return the desired fan mode of operation."""
return self.thermostat['runtime']['desiredFanMode']
@property
def fan(self):
"""Return the current fan state."""
if 'fan' in self.thermostat['equipmentStatus']:
return STATE_ON
else:
return STATE_OFF
@property
def operation(self):
"""Return current operation ie. heat, cool, idle."""
status = self.thermostat['equipmentStatus']
if status == '':
return STATE_IDLE
elif 'Cool' in status:
return STATE_COOL
elif 'auxHeat' in status:
return STATE_HEAT
elif 'heatPump' in status:
return STATE_HEAT
else:
return status
@property
def mode(self):
"""Return current mode ie. home, away, sleep."""
return self.thermostat['program']['currentClimateRef']
@property
def hvac_mode(self):
"""Return current hvac mode ie. auto, auxHeatOnly, cool, heat, off."""
return self.thermostat['settings']['hvacMode']
@property
def fan_min_on_time(self):
"""Return current fan minimum on time."""
return self.thermostat['settings']['fanMinOnTime']
@property
def device_state_attributes(self):
"""Return device specific state attributes."""
# Move these to Thermostat Device and make them global
return {
"humidity": self.humidity,
"fan": self.fan,
"mode": self.mode,
"hvac_mode": self.hvac_mode,
"fan_min_on_time": self.fan_min_on_time
}
@property
def is_away_mode_on(self):
"""Return true if away mode is on."""
mode = self.mode
events = self.thermostat['events']
for event in events:
if event['running']:
mode = event['holdClimateRef']
break
return 'away' in mode
def turn_away_mode_on(self):
"""Turn away on."""
if self.hold_temp:
self.data.ecobee.set_climate_hold(self.thermostat_index,
"away", "indefinite")
else:
self.data.ecobee.set_climate_hold(self.thermostat_index, "away")
def turn_away_mode_off(self):
"""Turn away off."""
self.data.ecobee.resume_program(self.thermostat_index)
def set_temperature(self, temperature):
"""Set new target temperature."""
temperature = int(temperature)
low_temp = temperature - 1
high_temp = temperature + 1
if self.hold_temp:
self.data.ecobee.set_hold_temp(self.thermostat_index, low_temp,
high_temp, "indefinite")
else:
self.data.ecobee.set_hold_temp(self.thermostat_index, low_temp,
high_temp)
def set_hvac_mode(self, mode):
"""Set HVAC mode (auto, auxHeatOnly, cool, heat, off)."""
self.data.ecobee.set_hvac_mode(self.thermostat_index, mode)
def set_fan_min_on_time(self, fan_min_on_time):
"""Set the minimum fan on time."""
self.data.ecobee.set_fan_min_on_time(self.thermostat_index,
fan_min_on_time)
# Home and Sleep mode aren't used in UI yet:
# def turn_home_mode_on(self):
# """ Turns home mode on. """
# self.data.ecobee.set_climate_hold(self.thermostat_index, "home")
# def turn_home_mode_off(self):
# """ Turns home mode off. """
# self.data.ecobee.resume_program(self.thermostat_index)
# def turn_sleep_mode_on(self):
# """ Turns sleep mode on. """
# self.data.ecobee.set_climate_hold(self.thermostat_index, "sleep")
# def turn_sleep_mode_off(self):
# """ Turns sleep mode off. """
# self.data.ecobee.resume_program(self.thermostat_index)

View File

@ -1,90 +0,0 @@
"""
Support for eq3 Bluetooth Smart thermostats.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/thermostat.eq3btsmart/
"""
import logging
from homeassistant.components.thermostat import ThermostatDevice
from homeassistant.const import TEMP_CELSIUS
from homeassistant.util.temperature import convert
REQUIREMENTS = ['bluepy_devices==0.2.0']
CONF_MAC = 'mac'
CONF_DEVICES = 'devices'
CONF_ID = 'id'
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the eq3 BLE thermostats."""
devices = []
for name, device_cfg in config[CONF_DEVICES].items():
mac = device_cfg[CONF_MAC]
devices.append(EQ3BTSmartThermostat(mac, name))
add_devices(devices)
return True
# pylint: disable=too-many-instance-attributes, import-error, abstract-method
class EQ3BTSmartThermostat(ThermostatDevice):
"""Representation of a EQ3 Bluetooth Smart thermostat."""
def __init__(self, _mac, _name):
"""Initialize the thermostat."""
from bluepy_devices.devices import eq3btsmart
self._name = _name
self._thermostat = eq3btsmart.EQ3BTSmartThermostat(_mac)
@property
def name(self):
"""Return the name of the device."""
return self._name
@property
def unit_of_measurement(self):
"""Return the unit of measurement that is used."""
return TEMP_CELSIUS
@property
def current_temperature(self):
"""Can not report temperature, so return target_temperature."""
return self.target_temperature
@property
def target_temperature(self):
"""Return the temperature we try to reach."""
return self._thermostat.target_temperature
def set_temperature(self, temperature):
"""Set new target temperature."""
self._thermostat.target_temperature = temperature
@property
def device_state_attributes(self):
"""Return the device specific state attributes."""
return {"mode": self._thermostat.mode,
"mode_readable": self._thermostat.mode_readable}
@property
def min_temp(self):
"""Return the minimum temperature."""
return convert(self._thermostat.min_temp, TEMP_CELSIUS,
self.unit_of_measurement)
@property
def max_temp(self):
"""Return the maximum temperature."""
return convert(self._thermostat.max_temp, TEMP_CELSIUS,
self.unit_of_measurement)
def update(self):
"""Update the data from the thermostat."""
self._thermostat.update()

View File

@ -1,215 +0,0 @@
"""
Adds support for heat control units.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/thermostat.heat_control/
"""
import logging
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant.components import switch
from homeassistant.components.thermostat import (
STATE_HEAT, STATE_COOL, STATE_IDLE, ThermostatDevice)
from homeassistant.const import ATTR_UNIT_OF_MEASUREMENT, STATE_ON, STATE_OFF
from homeassistant.helpers import condition
from homeassistant.helpers.event import track_state_change
DEPENDENCIES = ['switch', 'sensor']
TOL_TEMP = 0.3
CONF_NAME = 'name'
DEFAULT_NAME = 'Heat Control'
CONF_HEATER = 'heater'
CONF_SENSOR = 'target_sensor'
CONF_MIN_TEMP = 'min_temp'
CONF_MAX_TEMP = 'max_temp'
CONF_TARGET_TEMP = 'target_temp'
CONF_AC_MODE = 'ac_mode'
CONF_MIN_DUR = 'min_cycle_duration'
_LOGGER = logging.getLogger(__name__)
PLATFORM_SCHEMA = vol.Schema({
vol.Required("platform"): "heat_control",
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Required(CONF_HEATER): cv.entity_id,
vol.Required(CONF_SENSOR): cv.entity_id,
vol.Optional(CONF_MIN_TEMP): vol.Coerce(float),
vol.Optional(CONF_MAX_TEMP): vol.Coerce(float),
vol.Optional(CONF_TARGET_TEMP): vol.Coerce(float),
vol.Optional(CONF_AC_MODE): vol.Coerce(bool),
vol.Optional(CONF_MIN_DUR): vol.All(cv.time_period, cv.positive_timedelta),
})
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the heat control thermostat."""
name = config.get(CONF_NAME)
heater_entity_id = config.get(CONF_HEATER)
sensor_entity_id = config.get(CONF_SENSOR)
min_temp = config.get(CONF_MIN_TEMP)
max_temp = config.get(CONF_MAX_TEMP)
target_temp = config.get(CONF_TARGET_TEMP)
ac_mode = config.get(CONF_AC_MODE)
min_cycle_duration = config.get(CONF_MIN_DUR)
add_devices([HeatControl(hass, name, heater_entity_id, sensor_entity_id,
min_temp, max_temp, target_temp, ac_mode,
min_cycle_duration)])
# pylint: disable=too-many-instance-attributes, abstract-method
class HeatControl(ThermostatDevice):
"""Representation of a HeatControl device."""
# pylint: disable=too-many-arguments
def __init__(self, hass, name, heater_entity_id, sensor_entity_id,
min_temp, max_temp, target_temp, ac_mode, min_cycle_duration):
"""Initialize the thermostat."""
self.hass = hass
self._name = name
self.heater_entity_id = heater_entity_id
self.ac_mode = ac_mode
self.min_cycle_duration = min_cycle_duration
self._active = False
self._cur_temp = None
self._min_temp = min_temp
self._max_temp = max_temp
self._target_temp = target_temp
self._unit = hass.config.units.temperature_unit
track_state_change(hass, sensor_entity_id, self._sensor_changed)
sensor_state = hass.states.get(sensor_entity_id)
if sensor_state:
self._update_temp(sensor_state)
@property
def should_poll(self):
"""No polling needed."""
return False
@property
def name(self):
"""Return the name of the thermostat."""
return self._name
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
return self._unit
@property
def current_temperature(self):
"""Return the sensor temperature."""
return self._cur_temp
@property
def operation(self):
"""Return current operation ie. heat, cool, idle."""
if self.ac_mode:
cooling = self._active and self._is_device_active
return STATE_COOL if cooling else STATE_IDLE
else:
heating = self._active and self._is_device_active
return STATE_HEAT if heating else STATE_IDLE
@property
def target_temperature(self):
"""Return the temperature we try to reach."""
return self._target_temp
def set_temperature(self, temperature):
"""Set new target temperature."""
self._target_temp = temperature
self._control_heating()
self.update_ha_state()
@property
def min_temp(self):
"""Return the minimum temperature."""
# pylint: disable=no-member
if self._min_temp:
return self._min_temp
else:
# get default temp from super class
return ThermostatDevice.min_temp.fget(self)
@property
def max_temp(self):
"""Return the maximum temperature."""
# pylint: disable=no-member
if self._min_temp:
return self._max_temp
else:
# Get default temp from super class
return ThermostatDevice.max_temp.fget(self)
def _sensor_changed(self, entity_id, old_state, new_state):
"""Called when temperature changes."""
if new_state is None:
return
self._update_temp(new_state)
self._control_heating()
self.update_ha_state()
def _update_temp(self, state):
"""Update thermostat with latest state from sensor."""
unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
try:
self._cur_temp = self.hass.config.units.temperature(
float(state.state), unit)
except ValueError as ex:
_LOGGER.error('Unable to update from sensor: %s', ex)
def _control_heating(self):
"""Check if we need to turn heating on or off."""
if not self._active and None not in (self._cur_temp,
self._target_temp):
self._active = True
_LOGGER.info('Obtained current and target temperature. '
'Heat control active.')
if not self._active:
return
if self.min_cycle_duration:
if self._is_device_active:
current_state = STATE_ON
else:
current_state = STATE_OFF
long_enough = condition.state(self.hass, self.heater_entity_id,
current_state,
self.min_cycle_duration)
if not long_enough:
return
if self.ac_mode:
too_hot = self._cur_temp - self._target_temp > TOL_TEMP
is_cooling = self._is_device_active
if too_hot and not is_cooling:
_LOGGER.info('Turning on AC %s', self.heater_entity_id)
switch.turn_on(self.hass, self.heater_entity_id)
elif not too_hot and is_cooling:
_LOGGER.info('Turning off AC %s', self.heater_entity_id)
switch.turn_off(self.hass, self.heater_entity_id)
else:
too_cold = self._target_temp - self._cur_temp > TOL_TEMP
is_heating = self._is_device_active
if too_cold and not is_heating:
_LOGGER.info('Turning on heater %s', self.heater_entity_id)
switch.turn_on(self.hass, self.heater_entity_id)
elif not too_cold and is_heating:
_LOGGER.info('Turning off heater %s', self.heater_entity_id)
switch.turn_off(self.hass, self.heater_entity_id)
@property
def _is_device_active(self):
"""If the toggleable device is currently active."""
return switch.is_on(self.hass, self.heater_entity_id)

View File

@ -1,114 +0,0 @@
"""
Support for the PRT Heatmiser themostats using the V3 protocol.
See https://github.com/andylockran/heatmiserV3 for more info on the
heatmiserV3 module dependency.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/thermostat.heatmiser/
"""
import logging
from homeassistant.components.thermostat import ThermostatDevice
from homeassistant.const import TEMP_CELSIUS
CONF_IPADDRESS = 'ipaddress'
CONF_PORT = 'port'
CONF_TSTATS = 'tstats'
REQUIREMENTS = ["heatmiserV3==0.9.1"]
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the heatmiser thermostat."""
from heatmiserV3 import heatmiser, connection
ipaddress = str(config[CONF_IPADDRESS])
port = str(config[CONF_PORT])
if ipaddress is None or port is None:
_LOGGER.error("Missing required configuration items %s or %s",
CONF_IPADDRESS, CONF_PORT)
return False
serport = connection.connection(ipaddress, port)
serport.open()
tstats = []
if CONF_TSTATS in config:
tstats = config[CONF_TSTATS]
if tstats is None:
_LOGGER.error("No thermostats configured.")
return False
for tstat in tstats:
add_devices([
HeatmiserV3Thermostat(
heatmiser,
tstat.get("id"),
tstat.get("name"),
serport)
])
return
class HeatmiserV3Thermostat(ThermostatDevice):
"""Representation of a HeatmiserV3 thermostat."""
# pylint: disable=too-many-instance-attributes, abstract-method
def __init__(self, heatmiser, device, name, serport):
"""Initialize the thermostat."""
self.heatmiser = heatmiser
self.device = device
self.serport = serport
self._current_temperature = None
self._name = name
self._id = device
self.dcb = None
self.update()
self._target_temperature = int(self.dcb.get("roomset"))
@property
def name(self):
"""Return the name of the thermostat, if any."""
return self._name
@property
def unit_of_measurement(self):
"""Return the unit of measurement which this thermostat uses."""
return TEMP_CELSIUS
@property
def current_temperature(self):
"""Return the current temperature."""
if self.dcb is not None:
low = self.dcb.get("floortemplow ")
high = self.dcb.get("floortemphigh")
temp = (high*256 + low)/10.0
self._current_temperature = temp
else:
self._current_temperature = None
return self._current_temperature
@property
def target_temperature(self):
"""Return the temperature we try to reach."""
return self._target_temperature
def set_temperature(self, temperature):
"""Set new target temperature."""
temperature = int(temperature)
self.heatmiser.hmSendAddress(
self._id,
18,
temperature,
1,
self.serport)
self._target_temperature = int(temperature)
def update(self):
"""Get the latest data."""
self.dcb = self.heatmiser.hmReadAddress(self._id, 'prt', self.serport)

View File

@ -1,266 +0,0 @@
"""
Support for Honeywell Round Connected and Honeywell Evohome thermostats.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/thermostat.honeywell/
"""
import logging
import socket
from homeassistant.components.thermostat import ThermostatDevice
from homeassistant.const import (
CONF_PASSWORD, CONF_USERNAME, TEMP_CELSIUS, TEMP_FAHRENHEIT)
REQUIREMENTS = ['evohomeclient==0.2.5',
'somecomfort==0.3.2']
_LOGGER = logging.getLogger(__name__)
CONF_AWAY_TEMP = "away_temperature"
DEFAULT_AWAY_TEMP = 16
def _setup_round(username, password, config, add_devices):
"""Setup rounding function."""
from evohomeclient import EvohomeClient
try:
away_temp = float(config.get(CONF_AWAY_TEMP, DEFAULT_AWAY_TEMP))
except ValueError:
_LOGGER.error("value entered for item %s should convert to a number",
CONF_AWAY_TEMP)
return False
evo_api = EvohomeClient(username, password)
try:
zones = evo_api.temperatures(force_refresh=True)
for i, zone in enumerate(zones):
add_devices([RoundThermostat(evo_api,
zone['id'],
i == 0,
away_temp)])
except socket.error:
_LOGGER.error(
"Connection error logging into the honeywell evohome web service"
)
return False
return True
# config will be used later
def _setup_us(username, password, config, add_devices):
"""Setup user."""
import somecomfort
try:
client = somecomfort.SomeComfort(username, password)
except somecomfort.AuthError:
_LOGGER.error('Failed to login to honeywell account %s', username)
return False
except somecomfort.SomeComfortError as ex:
_LOGGER.error('Failed to initialize honeywell client: %s', str(ex))
return False
dev_id = config.get('thermostat')
loc_id = config.get('location')
add_devices([HoneywellUSThermostat(client, device)
for location in client.locations_by_id.values()
for device in location.devices_by_id.values()
if ((not loc_id or location.locationid == loc_id) and
(not dev_id or device.deviceid == dev_id))])
return True
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the honeywel thermostat."""
username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
region = config.get('region', 'eu').lower()
if username is None or password is None:
_LOGGER.error("Missing required configuration items %s or %s",
CONF_USERNAME, CONF_PASSWORD)
return False
if region not in ('us', 'eu'):
_LOGGER.error('Region `%s` is invalid (use either us or eu)', region)
return False
if region == 'us':
return _setup_us(username, password, config, add_devices)
else:
return _setup_round(username, password, config, add_devices)
class RoundThermostat(ThermostatDevice):
"""Representation of a Honeywell Round Connected thermostat."""
# pylint: disable=too-many-instance-attributes, abstract-method
def __init__(self, device, zone_id, master, away_temp):
"""Initialize the thermostat."""
self.device = device
self._current_temperature = None
self._target_temperature = None
self._name = "round connected"
self._id = zone_id
self._master = master
self._is_dhw = False
self._away_temp = away_temp
self._away = False
self.update()
@property
def name(self):
"""Return the name of the honeywell, if any."""
return self._name
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
return TEMP_CELSIUS
@property
def current_temperature(self):
"""Return the current temperature."""
return self._current_temperature
@property
def target_temperature(self):
"""Return the temperature we try to reach."""
if self._is_dhw:
return None
return self._target_temperature
def set_temperature(self, temperature):
"""Set new target temperature."""
self.device.set_temperature(self._name, temperature)
@property
def operation(self: ThermostatDevice) -> str:
"""Get the current operation of the system."""
return getattr(self.device, 'system_mode', None)
@property
def is_away_mode_on(self):
"""Return true if away mode is on."""
return self._away
def set_hvac_mode(self: ThermostatDevice, hvac_mode: str) -> None:
"""Set the HVAC mode for the thermostat."""
if hasattr(self.device, 'system_mode'):
self.device.system_mode = hvac_mode
def turn_away_mode_on(self):
"""Turn away on.
Evohome does have a proprietary away mode, but it doesn't really work
the way it should. For example: If you set a temperature manually
it doesn't get overwritten when away mode is switched on.
"""
self._away = True
self.device.set_temperature(self._name, self._away_temp)
def turn_away_mode_off(self):
"""Turn away off."""
self._away = False
self.device.cancel_temp_override(self._name)
def update(self):
"""Get the latest date."""
try:
# Only refresh if this is the "master" device,
# others will pick up the cache
for val in self.device.temperatures(force_refresh=self._master):
if val['id'] == self._id:
data = val
except StopIteration:
_LOGGER.error("Did not receive any temperature data from the "
"evohomeclient API.")
return
self._current_temperature = data['temp']
self._target_temperature = data['setpoint']
if data['thermostat'] == "DOMESTIC_HOT_WATER":
self._name = "Hot Water"
self._is_dhw = True
else:
self._name = data['name']
self._is_dhw = False
# pylint: disable=abstract-method
class HoneywellUSThermostat(ThermostatDevice):
"""Representation of a Honeywell US Thermostat."""
def __init__(self, client, device):
"""Initialize the thermostat."""
self._client = client
self._device = device
@property
def is_fan_on(self):
"""Return true if fan is on."""
return self._device.fan_running
@property
def name(self):
"""Return the name of the honeywell, if any."""
return self._device.name
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
return (TEMP_CELSIUS if self._device.temperature_unit == 'C'
else TEMP_FAHRENHEIT)
@property
def current_temperature(self):
"""Return the current temperature."""
self._device.refresh()
return self._device.current_temperature
@property
def target_temperature(self):
"""Return the temperature we try to reach."""
if self._device.system_mode == 'cool':
return self._device.setpoint_cool
else:
return self._device.setpoint_heat
@property
def operation(self: ThermostatDevice) -> str:
"""Return current operation ie. heat, cool, idle."""
return getattr(self._device, 'system_mode', None)
def set_temperature(self, temperature):
"""Set target temperature."""
import somecomfort
try:
if self._device.system_mode == 'cool':
self._device.setpoint_cool = temperature
else:
self._device.setpoint_heat = temperature
except somecomfort.SomeComfortError:
_LOGGER.error('Temperature %.1f out of range', temperature)
@property
def device_state_attributes(self):
"""Return the device specific state attributes."""
return {'fan': (self.is_fan_on and 'running' or 'idle'),
'fanmode': self._device.fan_mode,
'system_mode': self._device.system_mode}
def turn_away_mode_on(self):
"""Turn away on."""
pass
def turn_away_mode_off(self):
"""Turn away off."""
pass
def set_hvac_mode(self: ThermostatDevice, hvac_mode: str) -> None:
"""Set the system mode (Cool, Heat, etc)."""
if hasattr(self._device, 'system_mode'):
self._device.system_mode = hvac_mode

View File

@ -1,83 +0,0 @@
"""
Support for KNX thermostats.
For more details about this platform, please refer to the documentation
https://home-assistant.io/components/knx/
"""
import logging
from homeassistant.components.thermostat import ThermostatDevice
from homeassistant.const import TEMP_CELSIUS
from homeassistant.components.knx import (
KNXConfig, KNXMultiAddressDevice)
DEPENDENCIES = ["knx"]
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Create and add an entity based on the configuration."""
add_entities([
KNXThermostat(hass, KNXConfig(config))
])
class KNXThermostat(KNXMultiAddressDevice, ThermostatDevice):
"""Representation of a KNX thermostat.
A KNX thermostat will has the following parameters:
- temperature (current temperature)
- setpoint (target temperature in HASS terms)
- hvac mode selection (comfort/night/frost protection)
This version supports only polling. Messages from the KNX bus do not
automatically update the state of the thermostat (to be implemented
in future releases)
"""
def __init__(self, hass, config):
"""Initialize the thermostat based on the given configuration."""
KNXMultiAddressDevice.__init__(self, hass, config,
["temperature", "setpoint"],
["mode"])
self._unit_of_measurement = TEMP_CELSIUS # KNX always used celsius
self._away = False # not yet supported
self._is_fan_on = False # not yet supported
@property
def should_poll(self):
"""Polling is needed for the KNX thermostat."""
return True
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
return self._unit_of_measurement
@property
def current_temperature(self):
"""Return the current temperature."""
from knxip.conversion import knx2_to_float
return knx2_to_float(self.value("temperature"))
@property
def target_temperature(self):
"""Return the temperature we try to reach."""
from knxip.conversion import knx2_to_float
return knx2_to_float(self.value("setpoint"))
def set_temperature(self, temperature):
"""Set new target temperature."""
from knxip.conversion import float_to_knx2
self.set_value("setpoint", float_to_knx2(temperature))
_LOGGER.debug("Set target temperature to %s", temperature)
def set_hvac_mode(self, hvac_mode):
"""Set hvac mode."""
raise NotImplementedError()

View File

@ -1,189 +0,0 @@
"""
Support for Nest thermostats.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/thermostat.nest/
"""
import voluptuous as vol
import homeassistant.components.nest as nest
from homeassistant.components.thermostat import (
STATE_COOL, STATE_HEAT, STATE_IDLE, ThermostatDevice)
from homeassistant.const import TEMP_CELSIUS, CONF_PLATFORM, CONF_SCAN_INTERVAL
DEPENDENCIES = ['nest']
PLATFORM_SCHEMA = vol.Schema({
vol.Required(CONF_PLATFORM): nest.DOMAIN,
vol.Optional(CONF_SCAN_INTERVAL):
vol.All(vol.Coerce(int), vol.Range(min=1)),
})
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Nest thermostat."""
add_devices([NestThermostat(structure, device)
for structure, device in nest.devices()])
# pylint: disable=abstract-method
class NestThermostat(ThermostatDevice):
"""Representation of a Nest thermostat."""
def __init__(self, structure, device):
"""Initialize the thermostat."""
self.structure = structure
self.device = device
@property
def name(self):
"""Return the name of the nest, if any."""
location = self.device.where
name = self.device.name
if location is None:
return name
else:
if name == '':
return location.capitalize()
else:
return location.capitalize() + '(' + name + ')'
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
return TEMP_CELSIUS
@property
def device_state_attributes(self):
"""Return the device specific state attributes."""
# Move these to Thermostat Device and make them global
return {
"humidity": self.device.humidity,
"target_humidity": self.device.target_humidity,
"mode": self.device.mode
}
@property
def current_temperature(self):
"""Return the current temperature."""
return self.device.temperature
@property
def operation(self):
"""Return current operation ie. heat, cool, idle."""
if self.device.hvac_ac_state is True:
return STATE_COOL
elif self.device.hvac_heater_state is True:
return STATE_HEAT
else:
return STATE_IDLE
@property
def target_temperature(self):
"""Return the temperature we try to reach."""
if self.device.mode == 'range':
low, high = self.target_temperature_low, \
self.target_temperature_high
if self.operation == STATE_COOL:
temp = high
elif self.operation == STATE_HEAT:
temp = low
else:
# If the outside temp is lower than the current temp, consider
# the 'low' temp to the target, otherwise use the high temp
if (self.device.structure.weather.current.temperature <
self.current_temperature):
temp = low
else:
temp = high
else:
if self.is_away_mode_on:
# away_temperature is a low, high tuple. Only one should be set
# if not in range mode, the other will be None
temp = self.device.away_temperature[0] or \
self.device.away_temperature[1]
else:
temp = self.device.target
return temp
@property
def target_temperature_low(self):
"""Return the lower bound temperature we try to reach."""
if self.is_away_mode_on and self.device.away_temperature[0]:
# away_temperature is always a low, high tuple
return self.device.away_temperature[0]
if self.device.mode == 'range':
return self.device.target[0]
return self.target_temperature
@property
def target_temperature_high(self):
"""Return the upper bound temperature we try to reach."""
if self.is_away_mode_on and self.device.away_temperature[1]:
# away_temperature is always a low, high tuple
return self.device.away_temperature[1]
if self.device.mode == 'range':
return self.device.target[1]
return self.target_temperature
@property
def is_away_mode_on(self):
"""Return if away mode is on."""
return self.structure.away
def set_temperature(self, temperature):
"""Set new target temperature."""
if self.device.mode == 'range':
if self.target_temperature == self.target_temperature_low:
temperature = (temperature, self.target_temperature_high)
elif self.target_temperature == self.target_temperature_high:
temperature = (self.target_temperature_low, temperature)
self.device.target = temperature
def set_hvac_mode(self, hvac_mode):
"""Set hvac mode."""
self.device.mode = hvac_mode
def turn_away_mode_on(self):
"""Turn away on."""
self.structure.away = True
def turn_away_mode_off(self):
"""Turn away off."""
self.structure.away = False
@property
def is_fan_on(self):
"""Return whether the fan is on."""
return self.device.fan
def turn_fan_on(self):
"""Turn fan on."""
self.device.fan = True
def turn_fan_off(self):
"""Turn fan off."""
self.device.fan = False
@property
def min_temp(self):
"""Identify min_temp in Nest API or defaults if not available."""
temp = self.device.away_temperature.low
if temp is None:
return super().min_temp
else:
return temp
@property
def max_temp(self):
"""Identify max_temp in Nest API or defaults if not available."""
temp = self.device.away_temperature.high
if temp is None:
return super().max_temp
else:
return temp
def update(self):
"""Python-nest has its own mechanism for staying up to date."""
pass

View File

@ -1,90 +0,0 @@
"""
Support for Proliphix NT10e Thermostats.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/thermostat.proliphix/
"""
from homeassistant.components.thermostat import (
STATE_COOL, STATE_HEAT, STATE_IDLE, ThermostatDevice)
from homeassistant.const import (
CONF_HOST, CONF_PASSWORD, CONF_USERNAME, TEMP_FAHRENHEIT)
REQUIREMENTS = ['proliphix==0.4.0']
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Proliphix thermostats."""
username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
host = config.get(CONF_HOST)
import proliphix
pdp = proliphix.PDP(host, username, password)
add_devices([
ProliphixThermostat(pdp)
])
# pylint: disable=abstract-method
class ProliphixThermostat(ThermostatDevice):
"""Representation a Proliphix thermostat."""
def __init__(self, pdp):
"""Initialize the thermostat."""
self._pdp = pdp
# initial data
self._pdp.update()
self._name = self._pdp.name
@property
def should_poll(self):
"""Polling needed for thermostat."""
return True
def update(self):
"""Update the data from the thermostat."""
self._pdp.update()
@property
def name(self):
"""Return the name of the thermostat."""
return self._name
@property
def device_state_attributes(self):
"""Return the device specific state attributes."""
return {
"fan": self._pdp.fan_state
}
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
return TEMP_FAHRENHEIT
@property
def current_temperature(self):
"""Return the current temperature."""
return self._pdp.cur_temp
@property
def target_temperature(self):
"""Return the temperature we try to reach."""
return self._pdp.setback
@property
def operation(self):
"""Return the current state of the thermostat."""
state = self._pdp.hvac_state
if state in (1, 2):
return STATE_IDLE
elif state == 3:
return STATE_HEAT
elif state == 6:
return STATE_COOL
def set_temperature(self, temperature):
"""Set new target temperature."""
self._pdp.setback = temperature

View File

@ -1,136 +0,0 @@
"""
Support for Radio Thermostat wifi-enabled home thermostats.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/thermostat.radiotherm/
"""
import datetime
import logging
from urllib.error import URLError
from homeassistant.components.thermostat import (
STATE_AUTO, STATE_COOL, STATE_HEAT, STATE_IDLE, STATE_OFF,
ThermostatDevice)
from homeassistant.const import CONF_HOST, TEMP_FAHRENHEIT
REQUIREMENTS = ['radiotherm==1.2']
HOLD_TEMP = 'hold_temp'
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Radio Thermostat."""
import radiotherm
hosts = []
if CONF_HOST in config:
hosts = config[CONF_HOST]
else:
hosts.append(radiotherm.discover.discover_address())
if hosts is None:
_LOGGER.error("No radiotherm thermostats detected.")
return False
hold_temp = config.get(HOLD_TEMP, False)
tstats = []
for host in hosts:
try:
tstat = radiotherm.get_thermostat(host)
tstats.append(RadioThermostat(tstat, hold_temp))
except (URLError, OSError):
_LOGGER.exception("Unable to connect to Radio Thermostat: %s",
host)
add_devices(tstats)
# pylint: disable=abstract-method
class RadioThermostat(ThermostatDevice):
"""Representation of a Radio Thermostat."""
def __init__(self, device, hold_temp):
"""Initialize the thermostat."""
self.device = device
self.set_time()
self._target_temperature = None
self._current_temperature = None
self._operation = STATE_IDLE
self._name = None
self.hold_temp = hold_temp
self.update()
@property
def name(self):
"""Return the name of the Radio Thermostat."""
return self._name
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
return TEMP_FAHRENHEIT
@property
def device_state_attributes(self):
"""Return the device specific state attributes."""
return {
"fan": self.device.fmode['human'],
"mode": self.device.tmode['human']
}
@property
def current_temperature(self):
"""Return the current temperature."""
return self._current_temperature
@property
def operation(self):
"""Return the current operation. head, cool idle."""
return self._operation
@property
def target_temperature(self):
"""Return the temperature we try to reach."""
return self._target_temperature
def update(self):
"""Update the data from the thermostat."""
self._current_temperature = self.device.temp['raw']
self._name = self.device.name['raw']
if self.device.tmode['human'] == 'Cool':
self._target_temperature = self.device.t_cool['raw']
self._operation = STATE_COOL
elif self.device.tmode['human'] == 'Heat':
self._target_temperature = self.device.t_heat['raw']
self._operation = STATE_HEAT
else:
self._operation = STATE_IDLE
def set_temperature(self, temperature):
"""Set new target temperature."""
if self._operation == STATE_COOL:
self.device.t_cool = temperature
elif self._operation == STATE_HEAT:
self.device.t_heat = temperature
if self.hold_temp:
self.device.hold = 1
else:
self.device.hold = 0
def set_time(self):
"""Set device time."""
now = datetime.datetime.now()
self.device.time = {'day': now.weekday(),
'hour': now.hour, 'minute': now.minute}
def set_hvac_mode(self, mode):
"""Set HVAC mode (auto, cool, heat, off)."""
if mode == STATE_OFF:
self.device.tmode = 0
elif mode == STATE_AUTO:
self.device.tmode = 3
elif mode == STATE_COOL:
self.device.t_cool = self._target_temperature
elif mode == STATE_HEAT:
self.device.t_heat = self._target_temperature

View File

@ -1,48 +0,0 @@
set_away_mode:
description: Turn away mode on/off for a thermostat
fields:
entity_id:
description: Name(s) of entities to change
example: 'light.kitchen'
away_mode:
description: New value of away mode
example: true
set_temperature:
description: Set temperature of thermostat
fields:
entity_id:
description: Name(s) of entities to change
example: 'light.kitchen'
temperature:
description: New target temperature for thermostat
example: 25
set_fan_mode:
description: Turn fan on/off for a thermostat
fields:
entity_id:
description: Name(s) of entities to change
example: 'thermostat.nest'
fan:
description: New value of fan mode
example: true
ecobee_set_fan_min_on_time:
description: Set the minimum time, in minutes, to run the fan each hour
fields:
entity_id:
descriptions: Name(s) of entities to change
example: 'thermostat.ecobee'
fan_min_on_time:
description: New value of fan minimum on time
example: 5

View File

@ -1,168 +0,0 @@
"""ZWave Thermostat."""
# Because we do not compile openzwave on CI
# pylint: disable=import-error
import logging
from homeassistant.components.thermostat import DOMAIN
from homeassistant.components.thermostat import (
ThermostatDevice,
STATE_IDLE)
from homeassistant.components import zwave
from homeassistant.const import TEMP_FAHRENHEIT, TEMP_CELSIUS
_LOGGER = logging.getLogger(__name__)
CONF_NAME = 'name'
DEFAULT_NAME = 'ZWave Thermostat'
REMOTEC = 0x5254
REMOTEC_ZXT_120 = 0x8377
REMOTEC_ZXT_120_THERMOSTAT = (REMOTEC, REMOTEC_ZXT_120)
WORKAROUND_IGNORE = 'ignore'
DEVICE_MAPPINGS = {
REMOTEC_ZXT_120_THERMOSTAT: WORKAROUND_IGNORE
}
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the ZWave thermostats."""
if discovery_info is None or zwave.NETWORK is None:
_LOGGER.debug("No discovery_info=%s or no NETWORK=%s",
discovery_info, zwave.NETWORK)
return
node = zwave.NETWORK.nodes[discovery_info[zwave.const.ATTR_NODE_ID]]
value = node.values[discovery_info[zwave.const.ATTR_VALUE_ID]]
value.set_change_verified(False)
# Make sure that we have values for the key before converting to int
if (value.node.manufacturer_id.strip() and
value.node.product_id.strip()):
specific_sensor_key = (int(value.node.manufacturer_id, 16),
int(value.node.product_id, 16))
if specific_sensor_key in DEVICE_MAPPINGS:
if DEVICE_MAPPINGS[specific_sensor_key] == WORKAROUND_IGNORE:
_LOGGER.debug("Remotec ZXT-120 Zwave Thermostat, ignoring")
return
if not (value.node.get_values_for_command_class(
zwave.const.COMMAND_CLASS_SENSOR_MULTILEVEL) and
value.node.get_values_for_command_class(
zwave.const.COMMAND_CLASS_THERMOSTAT_SETPOINT)):
return
if value.command_class != zwave.const.COMMAND_CLASS_SENSOR_MULTILEVEL and \
value.command_class != zwave.const.COMMAND_CLASS_THERMOSTAT_SETPOINT:
return
add_devices([ZWaveThermostat(value)])
_LOGGER.debug("discovery_info=%s and zwave.NETWORK=%s",
discovery_info, zwave.NETWORK)
# pylint: disable=too-many-arguments, too-many-instance-attributes
# pylint: disable=abstract-method
class ZWaveThermostat(zwave.ZWaveDeviceEntity, ThermostatDevice):
"""Represents a HeatControl thermostat."""
def __init__(self, value):
"""Initialize the zwave thermostat."""
from openzwave.network import ZWaveNetwork
from pydispatch import dispatcher
zwave.ZWaveDeviceEntity.__init__(self, value, DOMAIN)
self._node = value.node
self._index = value.index
self._current_temperature = None
self._unit = None
self._current_operation_state = STATE_IDLE
self._target_temperature = None
self._current_fan_state = STATE_IDLE
self.update_properties()
# register listener
dispatcher.connect(
self.value_changed, ZWaveNetwork.SIGNAL_VALUE_CHANGED)
def value_changed(self, value):
"""Called when a value has changed on the network."""
if self._value.value_id == value.value_id or \
self._value.node == value.node:
self.update_properties()
self.update_ha_state()
def update_properties(self):
"""Callback on data change for the registered node/value pair."""
# current Temp
for _, value in self._node.get_values_for_command_class(
zwave.const.COMMAND_CLASS_SENSOR_MULTILEVEL).items():
if value.label == 'Temperature':
self._current_temperature = int(value.data)
self._unit = value.units
# operation state
for _, value in (self._node.get_values(
class_id=zwave.const.COMMAND_CLASS_THERMOSTAT_OPERATING_STATE)
.items()):
self._current_operation_state = value.data_as_string
# target temperature
temps = []
for _, value in (self._node.get_values(
class_id=zwave.const.COMMAND_CLASS_THERMOSTAT_SETPOINT)
.items()):
temps.append(int(value.data))
if value.index == self._index:
self._target_temperature = value.data
self._target_temperature_high = max(temps)
self._target_temperature_low = min(temps)
# fan state
for _, value in (self._node.get_values(
class_id=zwave.const.COMMAND_CLASS_THERMOSTAT_FAN_STATE)
.items()):
self._current_fan_state = value.data_as_string
@property
def should_poll(self):
"""No polling on ZWave."""
return False
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
unit = self._unit
if unit == 'C':
return TEMP_CELSIUS
elif unit == 'F':
return TEMP_FAHRENHEIT
else:
return unit
@property
def current_temperature(self):
"""Return the current temperature."""
return self._current_temperature
@property
def operation(self):
"""Return current operation ie. heat, cool, idle."""
return self._current_operation_state
@property
def target_temperature(self):
"""Return the temperature we try to reach."""
return self._target_temperature
@property
def is_fan_on(self):
"""Return true if the fan is on."""
return not (self._current_fan_state == 'Idle' or
self._current_fan_state == STATE_IDLE)
def set_temperature(self, temperature):
"""Set new target temperature."""
# set point
for _, value in self._node.get_values_for_command_class(
zwave.const.COMMAND_CLASS_THERMOSTAT_SETPOINT).items():
if int(value.data) != 0 and value.index == self._index:
value.data = temperature
break

View File

@ -314,11 +314,6 @@ SERVICE_SET_COVER_TILT_POSITION = 'set_cover_tilt_position'
SERVICE_STOP_COVER = 'stop_cover'
SERVICE_STOP_COVER_TILT = 'stop_cover_tilt'
SERVICE_MOVE_UP = 'move_up'
SERVICE_MOVE_DOWN = 'move_down'
SERVICE_MOVE_POSITION = 'move_position'
SERVICE_STOP = 'stop'
# #### API / REMOTE ####
SERVER_PORT = 8123

View File

@ -14,25 +14,24 @@ from homeassistant.components.sun import (
STATE_ABOVE_HORIZON, STATE_BELOW_HORIZON)
from homeassistant.components.switch.mysensors import (
ATTR_IR_CODE, SERVICE_SEND_IR_CODE)
from homeassistant.components.thermostat import (
ATTR_AWAY_MODE, ATTR_FAN, SERVICE_SET_AWAY_MODE, SERVICE_SET_FAN_MODE,
from homeassistant.components.climate import (
ATTR_AUX_HEAT, ATTR_AWAY_MODE, ATTR_FAN_MODE, ATTR_HUMIDITY,
ATTR_OPERATION_MODE, ATTR_SWING_MODE,
SERVICE_SET_AUX_HEAT, SERVICE_SET_AWAY_MODE, SERVICE_SET_FAN_MODE,
SERVICE_SET_HUMIDITY, SERVICE_SET_OPERATION_MODE, SERVICE_SET_SWING_MODE,
SERVICE_SET_TEMPERATURE)
from homeassistant.components.thermostat.ecobee import (
from homeassistant.components.climate.ecobee import (
ATTR_FAN_MIN_ON_TIME, SERVICE_SET_FAN_MIN_ON_TIME)
from homeassistant.components.hvac import (
ATTR_HUMIDITY, ATTR_SWING_MODE, ATTR_OPERATION_MODE, ATTR_AUX_HEAT,
SERVICE_SET_HUMIDITY, SERVICE_SET_SWING_MODE,
SERVICE_SET_OPERATION_MODE, SERVICE_SET_AUX_HEAT)
from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_TEMPERATURE, SERVICE_ALARM_ARM_AWAY,
SERVICE_ALARM_ARM_HOME, SERVICE_ALARM_DISARM, SERVICE_ALARM_TRIGGER,
SERVICE_CLOSE, SERVICE_LOCK, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY,
SERVICE_MEDIA_SEEK, SERVICE_MOVE_DOWN, SERVICE_MOVE_UP, SERVICE_OPEN,
SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_UNLOCK, SERVICE_VOLUME_MUTE,
SERVICE_VOLUME_SET, SERVICE_OPEN_COVER, SERVICE_CLOSE_COVER,
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED,
STATE_ALARM_TRIGGERED, STATE_CLOSED, STATE_LOCKED, STATE_OFF, STATE_ON,
STATE_OPEN, STATE_PAUSED, STATE_PLAYING, STATE_UNKNOWN, STATE_UNLOCKED)
SERVICE_LOCK, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY,
SERVICE_MEDIA_SEEK, SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_UNLOCK,
SERVICE_VOLUME_MUTE, SERVICE_VOLUME_SET, SERVICE_OPEN_COVER,
SERVICE_CLOSE_COVER, STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME,
STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED, STATE_CLOSED, STATE_LOCKED,
STATE_OFF, STATE_ON, STATE_OPEN, STATE_PAUSED, STATE_PLAYING,
STATE_UNKNOWN, STATE_UNLOCKED)
from homeassistant.core import State
_LOGGER = logging.getLogger(__name__)
@ -49,7 +48,7 @@ SERVICE_ATTRIBUTES = {
SERVICE_VOLUME_SET: [ATTR_MEDIA_VOLUME_LEVEL],
SERVICE_NOTIFY: [ATTR_MESSAGE],
SERVICE_SET_AWAY_MODE: [ATTR_AWAY_MODE],
SERVICE_SET_FAN_MODE: [ATTR_FAN],
SERVICE_SET_FAN_MODE: [ATTR_FAN_MODE],
SERVICE_SET_FAN_MIN_ON_TIME: [ATTR_FAN_MIN_ON_TIME],
SERVICE_SET_TEMPERATURE: [ATTR_TEMPERATURE],
SERVICE_SET_HUMIDITY: [ATTR_HUMIDITY],
@ -73,10 +72,6 @@ SERVICE_TO_STATE = {
SERVICE_ALARM_TRIGGER: STATE_ALARM_TRIGGERED,
SERVICE_LOCK: STATE_LOCKED,
SERVICE_UNLOCK: STATE_UNLOCKED,
SERVICE_CLOSE: STATE_CLOSED,
SERVICE_OPEN: STATE_OPEN,
SERVICE_MOVE_UP: STATE_OPEN,
SERVICE_MOVE_DOWN: STATE_CLOSED,
SERVICE_OPEN_COVER: STATE_OPEN,
SERVICE_CLOSE_COVER: STATE_CLOSED
}

View File

@ -55,7 +55,6 @@ blinkstick==1.1.8
blockchain==1.3.3
# homeassistant.components.climate.eq3btsmart
# homeassistant.components.thermostat.eq3btsmart
# bluepy_devices==0.2.0
# homeassistant.components.notify.aws_lambda
@ -96,7 +95,6 @@ enocean==0.31
# evdev==0.6.1
# homeassistant.components.climate.honeywell
# homeassistant.components.thermostat.honeywell
evohomeclient==0.2.5
# homeassistant.components.sensor.fastdotcom
@ -139,7 +137,6 @@ ha-ffmpeg==0.14
hbmqtt==0.7.1
# homeassistant.components.climate.heatmiser
# homeassistant.components.thermostat.heatmiser
heatmiserV3==0.9.1
# homeassistant.components.switch.hikvisioncam
@ -308,7 +305,6 @@ plexapi==2.0.2
pmsensor==0.3
# homeassistant.components.climate.proliphix
# homeassistant.components.thermostat.proliphix
proliphix==0.4.0
# homeassistant.components.sensor.systemmonitor
@ -440,7 +436,6 @@ pyvera==0.2.20
pywemo==0.4.7
# homeassistant.components.climate.radiotherm
# homeassistant.components.thermostat.radiotherm
radiotherm==1.2
# homeassistant.components.switch.rpi_rf
@ -474,7 +469,6 @@ sleepyq==0.6
snapcast==1.2.2
# homeassistant.components.climate.honeywell
# homeassistant.components.thermostat.honeywell
somecomfort==0.3.2
# homeassistant.components.sensor.speedtest

View File

@ -1 +0,0 @@
"""The tests for Garage door platforms."""

View File

@ -1,50 +0,0 @@
"""The tests for the Demo Garage door platform."""
import unittest
from homeassistant.bootstrap import setup_component
import homeassistant.components.garage_door as gd
from tests.common import get_test_home_assistant
LEFT = 'garage_door.left_garage_door'
RIGHT = 'garage_door.right_garage_door'
class TestGarageDoorDemo(unittest.TestCase):
"""Test the demo garage door."""
def setUp(self): # pylint: disable=invalid-name
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.assertTrue(setup_component(self.hass, gd.DOMAIN, {
'garage_door': {
'platform': 'demo'
}
}))
def tearDown(self): # pylint: disable=invalid-name
"""Stop everything that was started."""
self.hass.stop()
def test_is_closed(self):
"""Test if door is closed."""
self.assertTrue(gd.is_closed(self.hass, LEFT))
self.hass.states.is_state(LEFT, 'close')
self.assertFalse(gd.is_closed(self.hass, RIGHT))
self.hass.states.is_state(RIGHT, 'open')
def test_open_door(self):
"""Test opeing of the door."""
gd.open_door(self.hass, LEFT)
self.hass.block_till_done()
self.assertFalse(gd.is_closed(self.hass, LEFT))
def test_close_door(self):
"""Test closing ot the door."""
gd.close_door(self.hass, RIGHT)
self.hass.block_till_done()
self.assertTrue(gd.is_closed(self.hass, RIGHT))

View File

@ -1,138 +0,0 @@
"""The tests for the MQTT Garge door platform."""
import unittest
from homeassistant.bootstrap import setup_component
from homeassistant.const import STATE_OPEN, STATE_CLOSED, ATTR_ASSUMED_STATE
import homeassistant.components.garage_door as garage_door
from tests.common import (
mock_mqtt_component, fire_mqtt_message, get_test_home_assistant,
assert_setup_component)
class TestGarageDoorMQTT(unittest.TestCase):
"""Test the MQTT Garage door."""
# pylint: disable=invalid-name
def setUp(self):
"""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):
"""Test if command fails with command topic."""
self.hass.config.components = ['mqtt']
with assert_setup_component(0):
assert setup_component(self.hass, garage_door.DOMAIN, {
garage_door.DOMAIN: {
'platform': 'mqtt',
'name': 'test',
'state_topic': '/home/garage_door/door'
}
})
self.assertIsNone(self.hass.states.get('garage_door.test'))
def test_controlling_state_via_topic(self):
"""Test the controlling state via topic."""
with assert_setup_component(1):
assert setup_component(self.hass, garage_door.DOMAIN, {
garage_door.DOMAIN: {
'platform': 'mqtt',
'name': 'test',
'state_topic': 'state-topic',
'command_topic': 'command-topic',
'state_open': 1,
'state_closed': 0,
'service_open': 1,
'service_close': 0
}
})
state = self.hass.states.get('garage_door.test')
self.assertEqual(STATE_CLOSED, state.state)
self.assertIsNone(state.attributes.get(ATTR_ASSUMED_STATE))
fire_mqtt_message(self.hass, 'state-topic', '1')
self.hass.block_till_done()
state = self.hass.states.get('garage_door.test')
self.assertEqual(STATE_OPEN, state.state)
fire_mqtt_message(self.hass, 'state-topic', '0')
self.hass.block_till_done()
state = self.hass.states.get('garage_door.test')
self.assertEqual(STATE_CLOSED, state.state)
def test_sending_mqtt_commands_and_optimistic(self):
"""Test the sending MQTT commands in optimistic mode."""
with assert_setup_component(1):
assert setup_component(self.hass, garage_door.DOMAIN, {
garage_door.DOMAIN: {
'platform': 'mqtt',
'name': 'test',
'command_topic': 'command-topic',
'state_open': 'beer state open',
'state_closed': 'beer state closed',
'service_open': 'beer open',
'service_close': 'beer close',
'qos': '2'
}
})
state = self.hass.states.get('garage_door.test')
self.assertEqual(STATE_CLOSED, state.state)
self.assertTrue(state.attributes.get(ATTR_ASSUMED_STATE))
garage_door.open_door(self.hass, 'garage_door.test')
self.hass.block_till_done()
self.assertEqual(('command-topic', 'beer open', 2, False),
self.mock_publish.mock_calls[-1][1])
state = self.hass.states.get('garage_door.test')
self.assertEqual(STATE_OPEN, state.state)
garage_door.close_door(self.hass, 'garage_door.test')
self.hass.block_till_done()
self.assertEqual(('command-topic', 'beer close', 2, False),
self.mock_publish.mock_calls[-1][1])
state = self.hass.states.get('garage_door.test')
self.assertEqual(STATE_CLOSED, state.state)
def test_controlling_state_via_topic_and_json_message(self):
"""Test the controlling state via topic and JSON message."""
with assert_setup_component(1):
assert setup_component(self.hass, garage_door.DOMAIN, {
garage_door.DOMAIN: {
'platform': 'mqtt',
'name': 'test',
'state_topic': 'state-topic',
'command_topic': 'command-topic',
'state_open': 'beer open',
'state_closed': 'beer closed',
'service_open': 'beer service open',
'service_close': 'beer service close',
'value_template': '{{ value_json.val }}'
}
})
state = self.hass.states.get('garage_door.test')
self.assertEqual(STATE_CLOSED, state.state)
fire_mqtt_message(self.hass, 'state-topic', '{"val":"beer open"}')
self.hass.block_till_done()
state = self.hass.states.get('garage_door.test')
self.assertEqual(STATE_OPEN, state.state)
fire_mqtt_message(self.hass, 'state-topic', '{"val":"beer closed"}')
self.hass.block_till_done()
state = self.hass.states.get('garage_door.test')
self.assertEqual(STATE_CLOSED, state.state)

View File

@ -1 +0,0 @@
"""The tests for hvac component."""

View File

@ -1,167 +0,0 @@
"""The tests for the demo hvac."""
import unittest
from homeassistant.bootstrap import setup_component
from homeassistant.components import hvac
from homeassistant.util.unit_system import (
METRIC_SYSTEM,
)
from tests.common import get_test_home_assistant
ENTITY_HVAC = 'hvac.hvac'
class TestDemoHvac(unittest.TestCase):
"""Test the demo hvac."""
def setUp(self): # pylint: disable=invalid-name
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.units = METRIC_SYSTEM
self.assertTrue(setup_component(self.hass, hvac.DOMAIN, {'hvac': {
'platform': 'demo',
}}))
def tearDown(self): # pylint: disable=invalid-name
"""Stop down everything that was started."""
self.hass.stop()
def test_setup_params(self):
"""Test the inititial parameters."""
state = self.hass.states.get(ENTITY_HVAC)
self.assertEqual(21, state.attributes.get('temperature'))
self.assertEqual('on', state.attributes.get('away_mode'))
self.assertEqual(22, state.attributes.get('current_temperature'))
self.assertEqual("On High", state.attributes.get('fan_mode'))
self.assertEqual(67, state.attributes.get('humidity'))
self.assertEqual(54, state.attributes.get('current_humidity'))
self.assertEqual("Off", state.attributes.get('swing_mode'))
self.assertEqual("Cool", state.attributes.get('operation_mode'))
self.assertEqual('off', state.attributes.get('aux_heat'))
def test_default_setup_params(self):
"""Test the setup with default parameters."""
state = self.hass.states.get(ENTITY_HVAC)
self.assertEqual(19, state.attributes.get('min_temp'))
self.assertEqual(30, state.attributes.get('max_temp'))
self.assertEqual(30, state.attributes.get('min_humidity'))
self.assertEqual(99, state.attributes.get('max_humidity'))
def test_set_target_temp_bad_attr(self):
"""Test setting the target temperature without required attribute."""
state = self.hass.states.get(ENTITY_HVAC)
self.assertEqual(21, state.attributes.get('temperature'))
hvac.set_temperature(self.hass, None, ENTITY_HVAC)
self.hass.block_till_done()
self.assertEqual(21, state.attributes.get('temperature'))
def test_set_target_temp(self):
"""Test the setting of the target temperature."""
hvac.set_temperature(self.hass, 30, ENTITY_HVAC)
self.hass.block_till_done()
state = self.hass.states.get(ENTITY_HVAC)
self.assertEqual(30.0, state.attributes.get('temperature'))
def test_set_target_humidity_bad_attr(self):
"""Test setting the target humidity without required attribute."""
state = self.hass.states.get(ENTITY_HVAC)
self.assertEqual(67, state.attributes.get('humidity'))
hvac.set_humidity(self.hass, None, ENTITY_HVAC)
self.hass.block_till_done()
self.assertEqual(67, state.attributes.get('humidity'))
def test_set_target_humidity(self):
"""Test the setting of the target humidity."""
hvac.set_humidity(self.hass, 64, ENTITY_HVAC)
self.hass.block_till_done()
state = self.hass.states.get(ENTITY_HVAC)
self.assertEqual(64.0, state.attributes.get('humidity'))
def test_set_fan_mode_bad_attr(self):
"""Test setting fan mode without required attribute."""
state = self.hass.states.get(ENTITY_HVAC)
self.assertEqual("On High", state.attributes.get('fan_mode'))
hvac.set_fan_mode(self.hass, None, ENTITY_HVAC)
self.hass.block_till_done()
self.assertEqual("On High", state.attributes.get('fan_mode'))
def test_set_fan_mode(self):
"""Test setting of new fan mode."""
hvac.set_fan_mode(self.hass, "On Low", ENTITY_HVAC)
self.hass.block_till_done()
state = self.hass.states.get(ENTITY_HVAC)
self.assertEqual("On Low", state.attributes.get('fan_mode'))
def test_set_swing_mode_bad_attr(self):
"""Test setting swing mode without required attribute."""
state = self.hass.states.get(ENTITY_HVAC)
self.assertEqual("Off", state.attributes.get('swing_mode'))
hvac.set_swing_mode(self.hass, None, ENTITY_HVAC)
self.hass.block_till_done()
self.assertEqual("Off", state.attributes.get('swing_mode'))
def test_set_swing(self):
"""Test setting of new swing mode."""
hvac.set_swing_mode(self.hass, "Auto", ENTITY_HVAC)
self.hass.block_till_done()
state = self.hass.states.get(ENTITY_HVAC)
self.assertEqual("Auto", state.attributes.get('swing_mode'))
def test_set_operation_bad_attr(self):
"""Test setting operation mode without required attribute."""
self.assertEqual("Cool", self.hass.states.get(ENTITY_HVAC).state)
hvac.set_operation_mode(self.hass, None, ENTITY_HVAC)
self.hass.block_till_done()
self.assertEqual("Cool", self.hass.states.get(ENTITY_HVAC).state)
def test_set_operation(self):
"""Test setting of new operation mode."""
hvac.set_operation_mode(self.hass, "Heat", ENTITY_HVAC)
self.hass.block_till_done()
self.assertEqual("Heat", self.hass.states.get(ENTITY_HVAC).state)
def test_set_away_mode_bad_attr(self):
"""Test setting the away mode without required attribute."""
state = self.hass.states.get(ENTITY_HVAC)
self.assertEqual('on', state.attributes.get('away_mode'))
hvac.set_away_mode(self.hass, None, ENTITY_HVAC)
self.hass.block_till_done()
self.assertEqual('on', state.attributes.get('away_mode'))
def test_set_away_mode_on(self):
"""Test setting the away mode on/true."""
hvac.set_away_mode(self.hass, True, ENTITY_HVAC)
self.hass.block_till_done()
state = self.hass.states.get(ENTITY_HVAC)
self.assertEqual('on', state.attributes.get('away_mode'))
def test_set_away_mode_off(self):
"""Test setting the away mode off/false."""
hvac.set_away_mode(self.hass, False, ENTITY_HVAC)
self.hass.block_till_done()
state = self.hass.states.get(ENTITY_HVAC)
self.assertEqual('off', state.attributes.get('away_mode'))
def test_set_aux_heat_bad_attr(self):
"""Test setting the auxillary heater without required attribute."""
state = self.hass.states.get(ENTITY_HVAC)
self.assertEqual('off', state.attributes.get('aux_heat'))
hvac.set_aux_heat(self.hass, None, ENTITY_HVAC)
self.hass.block_till_done()
self.assertEqual('off', state.attributes.get('aux_heat'))
def test_set_aux_heat_on(self):
"""Test setting the axillary heater on/true."""
hvac.set_aux_heat(self.hass, True, ENTITY_HVAC)
self.hass.block_till_done()
state = self.hass.states.get(ENTITY_HVAC)
self.assertEqual('on', state.attributes.get('aux_heat'))
def test_set_aux_heat_off(self):
"""Test setting the auxillary heater off/false."""
hvac.set_aux_heat(self.hass, False, ENTITY_HVAC)
self.hass.block_till_done()
state = self.hass.states.get(ENTITY_HVAC)
self.assertEqual('off', state.attributes.get('aux_heat'))

View File

@ -1 +0,0 @@
"""The tests for Roller shutter platforms."""

View File

@ -1,88 +0,0 @@
"""The tests the Roller shutter command line platform."""
import os
import tempfile
import unittest
from unittest import mock
from homeassistant.bootstrap import setup_component
import homeassistant.components.rollershutter as rollershutter
from homeassistant.components.rollershutter import (
command_line as cmd_rs)
from tests.common import get_test_home_assistant
class TestCommandRollerShutter(unittest.TestCase):
"""Test the Roller shutter command line platform."""
def setup_method(self, method):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.latitude = 32.87336
self.hass.config.longitude = 117.22743
self.rs = cmd_rs.CommandRollershutter(self.hass, 'foo',
'cmd_up', 'cmd_dn',
'cmd_stop', 'cmd_state',
None) # FIXME
def teardown_method(self, method):
"""Stop down everything that was started."""
self.hass.stop()
def test_should_poll(self):
"""Test the setting of polling."""
self.assertTrue(self.rs.should_poll)
self.rs._command_state = None
self.assertFalse(self.rs.should_poll)
def test_query_state_value(self):
"""Test with state value."""
with mock.patch('subprocess.check_output') as mock_run:
mock_run.return_value = b' foo bar '
result = self.rs._query_state_value('runme')
self.assertEqual('foo bar', result)
self.assertEqual(mock_run.call_count, 1)
self.assertEqual(
mock_run.call_args, mock.call('runme', shell=True)
)
def test_state_value(self):
"""Test with state value."""
with tempfile.TemporaryDirectory() as tempdirname:
path = os.path.join(tempdirname, 'rollershutter_status')
test_rollershutter = {
'statecmd': 'cat {}'.format(path),
'upcmd': 'echo 1 > {}'.format(path),
'downcmd': 'echo 1 > {}'.format(path),
'stopcmd': 'echo 0 > {}'.format(path),
'value_template': '{{ value }}'
}
self.assertTrue(setup_component(self.hass, rollershutter.DOMAIN, {
'rollershutter': {
'platform': 'command_line',
'rollershutters': {
'test': test_rollershutter
}
}
}))
state = self.hass.states.get('rollershutter.test')
self.assertEqual('unknown', state.state)
rollershutter.move_up(self.hass, 'rollershutter.test')
self.hass.block_till_done()
state = self.hass.states.get('rollershutter.test')
self.assertEqual('open', state.state)
rollershutter.move_down(self.hass, 'rollershutter.test')
self.hass.block_till_done()
state = self.hass.states.get('rollershutter.test')
self.assertEqual('open', state.state)
rollershutter.stop(self.hass, 'rollershutter.test')
self.hass.block_till_done()
state = self.hass.states.get('rollershutter.test')
self.assertEqual('closed', state.state)

View File

@ -1,55 +0,0 @@
"""The tests for the Demo roller shutter platform."""
import unittest
import homeassistant.util.dt as dt_util
from homeassistant.components.rollershutter import demo
from tests.common import fire_time_changed, get_test_home_assistant
class TestRollershutterDemo(unittest.TestCase):
"""Test the Demo roller shutter."""
def setUp(self): # pylint: disable=invalid-name
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
def tearDown(self): # pylint: disable=invalid-name
"""Stop down everything that was started."""
self.hass.stop()
def test_move_up(self):
"""Test moving the rollershutter up."""
entity = demo.DemoRollershutter(self.hass, 'test', 100)
entity.move_up()
fire_time_changed(self.hass, dt_util.utcnow())
self.hass.block_till_done()
self.assertEqual(90, entity.current_position)
def test_move_down(self):
"""Test moving the rollershutter down."""
entity = demo.DemoRollershutter(self.hass, 'test', 0)
entity.move_down()
fire_time_changed(self.hass, dt_util.utcnow())
self.hass.block_till_done()
self.assertEqual(10, entity.current_position)
def test_move_position(self):
"""Test moving the rollershutter to a specific position."""
entity = demo.DemoRollershutter(self.hass, 'test', 0)
entity.move_position(10)
fire_time_changed(self.hass, dt_util.utcnow())
self.hass.block_till_done()
self.assertEqual(10, entity.current_position)
def test_stop(self):
"""Test stopping the rollershutter."""
entity = demo.DemoRollershutter(self.hass, 'test', 0)
entity.move_down()
entity.stop()
fire_time_changed(self.hass, dt_util.utcnow())
self.hass.block_till_done()
self.assertEqual(0, entity.current_position)

View File

@ -1,174 +0,0 @@
"""The tests for the MQTT roller shutter platform."""
import unittest
from homeassistant.bootstrap import _setup_component
from homeassistant.const import STATE_OPEN, STATE_CLOSED, STATE_UNKNOWN
import homeassistant.components.rollershutter as rollershutter
from tests.common import mock_mqtt_component, fire_mqtt_message
from tests.common import get_test_home_assistant
class TestRollershutterMQTT(unittest.TestCase):
"""Test the MQTT roller shutter."""
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 down everything that was started."""
self.hass.stop()
def test_controlling_state_via_topic(self):
"""Test the controlling state via topic."""
self.hass.config.components = ['mqtt']
assert _setup_component(self.hass, rollershutter.DOMAIN, {
rollershutter.DOMAIN: {
'platform': 'mqtt',
'name': 'test',
'state_topic': 'state-topic',
'command_topic': 'command-topic',
'qos': 0,
'payload_up': 'UP',
'payload_down': 'DOWN',
'payload_stop': 'STOP'
}
})
state = self.hass.states.get('rollershutter.test')
self.assertEqual(STATE_UNKNOWN, state.state)
fire_mqtt_message(self.hass, 'state-topic', '0')
self.hass.block_till_done()
state = self.hass.states.get('rollershutter.test')
self.assertEqual(STATE_CLOSED, state.state)
fire_mqtt_message(self.hass, 'state-topic', '50')
self.hass.block_till_done()
state = self.hass.states.get('rollershutter.test')
self.assertEqual(STATE_OPEN, state.state)
fire_mqtt_message(self.hass, 'state-topic', '100')
self.hass.block_till_done()
state = self.hass.states.get('rollershutter.test')
self.assertEqual(STATE_OPEN, state.state)
def test_send_move_up_command(self):
"""Test the sending of move_up."""
self.hass.config.components = ['mqtt']
assert _setup_component(self.hass, rollershutter.DOMAIN, {
rollershutter.DOMAIN: {
'platform': 'mqtt',
'name': 'test',
'state_topic': 'state-topic',
'command_topic': 'command-topic',
'qos': 2
}
})
state = self.hass.states.get('rollershutter.test')
self.assertEqual(STATE_UNKNOWN, state.state)
rollershutter.move_up(self.hass, 'rollershutter.test')
self.hass.block_till_done()
self.assertEqual(('command-topic', 'UP', 2, False),
self.mock_publish.mock_calls[-1][1])
state = self.hass.states.get('rollershutter.test')
self.assertEqual(STATE_UNKNOWN, state.state)
def test_send_move_down_command(self):
"""Test the sending of move_down."""
self.hass.config.components = ['mqtt']
assert _setup_component(self.hass, rollershutter.DOMAIN, {
rollershutter.DOMAIN: {
'platform': 'mqtt',
'name': 'test',
'state_topic': 'state-topic',
'command_topic': 'command-topic',
'qos': 2
}
})
state = self.hass.states.get('rollershutter.test')
self.assertEqual(STATE_UNKNOWN, state.state)
rollershutter.move_down(self.hass, 'rollershutter.test')
self.hass.block_till_done()
self.assertEqual(('command-topic', 'DOWN', 2, False),
self.mock_publish.mock_calls[-1][1])
state = self.hass.states.get('rollershutter.test')
self.assertEqual(STATE_UNKNOWN, state.state)
def test_send_stop_command(self):
"""Test the sending of stop."""
self.hass.config.components = ['mqtt']
assert _setup_component(self.hass, rollershutter.DOMAIN, {
rollershutter.DOMAIN: {
'platform': 'mqtt',
'name': 'test',
'state_topic': 'state-topic',
'command_topic': 'command-topic',
'qos': 2
}
})
state = self.hass.states.get('rollershutter.test')
self.assertEqual(STATE_UNKNOWN, state.state)
rollershutter.stop(self.hass, 'rollershutter.test')
self.hass.block_till_done()
self.assertEqual(('command-topic', 'STOP', 2, False),
self.mock_publish.mock_calls[-1][1])
state = self.hass.states.get('rollershutter.test')
self.assertEqual(STATE_UNKNOWN, state.state)
def test_state_attributes_current_position(self):
"""Test the current position."""
self.hass.config.components = ['mqtt']
assert _setup_component(self.hass, rollershutter.DOMAIN, {
rollershutter.DOMAIN: {
'platform': 'mqtt',
'name': 'test',
'state_topic': 'state-topic',
'command_topic': 'command-topic',
'payload_up': 'UP',
'payload_down': 'DOWN',
'payload_stop': 'STOP'
}
})
state_attributes_dict = self.hass.states.get(
'rollershutter.test').attributes
self.assertFalse('current_position' in state_attributes_dict)
fire_mqtt_message(self.hass, 'state-topic', '0')
self.hass.block_till_done()
current_position = self.hass.states.get(
'rollershutter.test').attributes['current_position']
self.assertEqual(0, current_position)
fire_mqtt_message(self.hass, 'state-topic', '50')
self.hass.block_till_done()
current_position = self.hass.states.get(
'rollershutter.test').attributes['current_position']
self.assertEqual(50, current_position)
fire_mqtt_message(self.hass, 'state-topic', '101')
self.hass.block_till_done()
current_position = self.hass.states.get(
'rollershutter.test').attributes['current_position']
self.assertEqual(50, current_position)
fire_mqtt_message(self.hass, 'state-topic', 'non-numeric')
self.hass.block_till_done()
current_position = self.hass.states.get(
'rollershutter.test').attributes['current_position']
self.assertEqual(50, current_position)

View File

@ -1,219 +0,0 @@
"""The tests for the Rfxtrx roller shutter platform."""
import unittest
import pytest
from homeassistant.bootstrap import _setup_component
from homeassistant.components import rfxtrx as rfxtrx_core
from tests.common import get_test_home_assistant
@pytest.mark.skipif("os.environ.get('RFXTRX') != 'RUN'")
class TestRollershutterRfxtrx(unittest.TestCase):
"""Test the Rfxtrx roller shutter platform."""
def setUp(self):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant(0)
self.hass.config.components = ['rfxtrx']
def tearDown(self):
"""Stop everything that was started."""
rfxtrx_core.RECEIVED_EVT_SUBSCRIBERS = []
rfxtrx_core.RFX_DEVICES = {}
if rfxtrx_core.RFXOBJECT:
rfxtrx_core.RFXOBJECT.close_connection()
self.hass.stop()
def test_valid_config(self):
"""Test configuration."""
self.assertTrue(_setup_component(self.hass, 'rollershutter', {
'rollershutter': {'platform': 'rfxtrx',
'automatic_add': True,
'devices':
{'0b1100cd0213c7f210010f51': {
'name': 'Test',
rfxtrx_core.ATTR_FIREEVENT: True}
}}}))
def test_invalid_config1(self):
"""Test configuration."""
self.assertFalse(_setup_component(self.hass, 'rollershutter', {
'rollershutter': {'platform': 'rfxtrx',
'automatic_add': True,
'devices':
{'2FF7f216': {
'name': 'Test',
'packetid': '0b1100cd0213c7f210010f51',
'signal_repetitions': 3}
}}}))
def test_invalid_config2(self):
"""Test configuration."""
self.assertFalse(_setup_component(self.hass, 'rollershutter', {
'rollershutter': {'platform': 'rfxtrx',
'automatic_add': True,
'invalid_key': 'afda',
'devices':
{'213c7f216': {
'name': 'Test',
'packetid': '0b1100cd0213c7f210010f51',
rfxtrx_core.ATTR_FIREEVENT: True}
}}}))
def test_invalid_config3(self):
"""Test configuration."""
self.assertFalse(_setup_component(self.hass, 'rollershutter', {
'rollershutter': {'platform': 'rfxtrx',
'automatic_add': True,
'devices':
{'213c7f216': {
'name': 'Test',
'packetid': 'AA1100cd0213c7f210010f51',
rfxtrx_core.ATTR_FIREEVENT: True}
}}}))
def test_invalid_config4(self):
"""Test configuration."""
self.assertFalse(_setup_component(self.hass, 'rollershutter', {
'rollershutter': {'platform': 'rfxtrx',
'automatic_add': True,
'devices':
{'213c7f216': {
'name': 'Test',
rfxtrx_core.ATTR_FIREEVENT: True}
}}}))
def test_default_config(self):
"""Test with 0 roller shutter."""
self.assertTrue(_setup_component(self.hass, 'rollershutter', {
'rollershutter': {'platform': 'rfxtrx',
'devices': {}}}))
self.assertEqual(0, len(rfxtrx_core.RFX_DEVICES))
def test_one_rollershutter(self):
"""Test with 1 roller shutter."""
self.assertTrue(_setup_component(self.hass, 'rollershutter', {
'rollershutter': {'platform': 'rfxtrx',
'devices':
{'0b1400cd0213c7f210010f51': {
'name': 'Test'
}}}}))
import RFXtrx as rfxtrxmod
rfxtrx_core.RFXOBJECT =\
rfxtrxmod.Core("", transport_protocol=rfxtrxmod.DummyTransport)
self.assertEqual(1, len(rfxtrx_core.RFX_DEVICES))
for id in rfxtrx_core.RFX_DEVICES:
entity = rfxtrx_core.RFX_DEVICES[id]
self.assertEqual(entity.signal_repetitions, 1)
self.assertFalse(entity.should_fire_event)
self.assertFalse(entity.should_poll)
entity.move_up()
entity.move_down()
entity.stop()
def test_several_rollershutters(self):
"""Test with 3 roller shutters."""
self.assertTrue(_setup_component(self.hass, 'rollershutter', {
'rollershutter': {'platform': 'rfxtrx',
'signal_repetitions': 3,
'devices':
{'0b1100cd0213c7f230010f71': {
'name': 'Test'},
'0b1100100118cdea02010f70': {
'name': 'Bath'},
'0b1100101118cdea02010f70': {
'name': 'Living'}
}}}))
self.assertEqual(3, len(rfxtrx_core.RFX_DEVICES))
device_num = 0
for id in rfxtrx_core.RFX_DEVICES:
entity = rfxtrx_core.RFX_DEVICES[id]
self.assertEqual(entity.signal_repetitions, 3)
if entity.name == 'Living':
device_num = device_num + 1
elif entity.name == 'Bath':
device_num = device_num + 1
elif entity.name == 'Test':
device_num = device_num + 1
self.assertEqual(3, device_num)
def test_discover_rollershutter(self):
"""Test with discovery of roller shutters."""
self.assertTrue(_setup_component(self.hass, 'rollershutter', {
'rollershutter': {'platform': 'rfxtrx',
'automatic_add': True,
'devices': {}}}))
event = rfxtrx_core.get_rfx_object('0a140002f38cae010f0070')
event.data = bytearray([0x0A, 0x14, 0x00, 0x02, 0xF3, 0x8C,
0xAE, 0x01, 0x0F, 0x00, 0x70])
for evt_sub in rfxtrx_core.RECEIVED_EVT_SUBSCRIBERS:
evt_sub(event)
self.assertEqual(1, len(rfxtrx_core.RFX_DEVICES))
event = rfxtrx_core.get_rfx_object('0a1400adf394ab020e0060')
event.data = bytearray([0x0A, 0x14, 0x00, 0xAD, 0xF3, 0x94,
0xAB, 0x02, 0x0E, 0x00, 0x60])
for evt_sub in rfxtrx_core.RECEIVED_EVT_SUBSCRIBERS:
evt_sub(event)
self.assertEqual(2, len(rfxtrx_core.RFX_DEVICES))
# Trying to add a sensor
event = rfxtrx_core.get_rfx_object('0a52085e070100b31b0279')
event.data = bytearray(b'\nR\x08^\x07\x01\x00\xb3\x1b\x02y')
for evt_sub in rfxtrx_core.RECEIVED_EVT_SUBSCRIBERS:
evt_sub(event)
self.assertEqual(2, len(rfxtrx_core.RFX_DEVICES))
# Trying to add a light
event = rfxtrx_core.get_rfx_object('0b1100100118cdea02010f70')
event.data = bytearray([0x0b, 0x11, 0x11, 0x10, 0x01, 0x18,
0xcd, 0xea, 0x01, 0x02, 0x0f, 0x70])
for evt_sub in rfxtrx_core.RECEIVED_EVT_SUBSCRIBERS:
evt_sub(event)
self.assertEqual(2, len(rfxtrx_core.RFX_DEVICES))
def test_discover_rollershutter_noautoadd(self):
"""Test with discovery of roller shutter when auto add is False."""
self.assertTrue(_setup_component(self.hass, 'rollershutter', {
'rollershutter': {'platform': 'rfxtrx',
'automatic_add': False,
'devices': {}}}))
event = rfxtrx_core.get_rfx_object('0a1400adf394ab010d0060')
event.data = bytearray([0x0A, 0x14, 0x00, 0xAD, 0xF3, 0x94,
0xAB, 0x01, 0x0D, 0x00, 0x60])
for evt_sub in rfxtrx_core.RECEIVED_EVT_SUBSCRIBERS:
evt_sub(event)
self.assertEqual(0, len(rfxtrx_core.RFX_DEVICES))
event = rfxtrx_core.get_rfx_object('0a1400adf394ab020e0060')
event.data = bytearray([0x0A, 0x14, 0x00, 0xAD, 0xF3, 0x94,
0xAB, 0x02, 0x0E, 0x00, 0x60])
for evt_sub in rfxtrx_core.RECEIVED_EVT_SUBSCRIBERS:
evt_sub(event)
self.assertEqual(0, len(rfxtrx_core.RFX_DEVICES))
# Trying to add a sensor
event = rfxtrx_core.get_rfx_object('0a52085e070100b31b0279')
event.data = bytearray(b'\nR\x08^\x07\x01\x00\xb3\x1b\x02y')
for evt_sub in rfxtrx_core.RECEIVED_EVT_SUBSCRIBERS:
evt_sub(event)
self.assertEqual(0, len(rfxtrx_core.RFX_DEVICES))
# Trying to add a light
event = rfxtrx_core.get_rfx_object('0b1100100118cdea02010f70')
event.data = bytearray([0x0b, 0x11, 0x11, 0x10, 0x01,
0x18, 0xcd, 0xea, 0x01, 0x02, 0x0f, 0x70])
for evt_sub in rfxtrx_core.RECEIVED_EVT_SUBSCRIBERS:
evt_sub(event)
self.assertEqual(0, len(rfxtrx_core.RFX_DEVICES))

View File

@ -1 +0,0 @@
"""The tests for Thermostat platforms."""

View File

@ -1,101 +0,0 @@
"""The tests for the demo thermostat."""
import unittest
from homeassistant.util.unit_system import (
METRIC_SYSTEM,
)
from homeassistant.components import thermostat
from tests.common import get_test_home_assistant
ENTITY_NEST = 'thermostat.nest'
class TestDemoThermostat(unittest.TestCase):
"""Test the Heat Control thermostat."""
def setUp(self): # pylint: disable=invalid-name
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.units = METRIC_SYSTEM
self.assertTrue(thermostat.setup(self.hass, {'thermostat': {
'platform': 'demo',
}}))
def tearDown(self): # pylint: disable=invalid-name
"""Stop down everything that was started."""
self.hass.stop()
def test_setup_params(self):
"""Test the inititial parameters."""
state = self.hass.states.get(ENTITY_NEST)
self.assertEqual(21, state.attributes.get('temperature'))
self.assertEqual('off', state.attributes.get('away_mode'))
self.assertEqual(19, state.attributes.get('current_temperature'))
self.assertEqual('off', state.attributes.get('fan'))
def test_default_setup_params(self):
"""Test the setup with default parameters."""
state = self.hass.states.get(ENTITY_NEST)
self.assertEqual(7, state.attributes.get('min_temp'))
self.assertEqual(35, state.attributes.get('max_temp'))
def test_set_target_temp_bad_attr(self):
"""Test setting the target temperature without required attribute."""
self.assertEqual('21.0', self.hass.states.get(ENTITY_NEST).state)
thermostat.set_temperature(self.hass, None, ENTITY_NEST)
self.hass.block_till_done()
self.assertEqual('21.0', self.hass.states.get(ENTITY_NEST).state)
def test_set_target_temp(self):
"""Test the setting of the target temperature."""
thermostat.set_temperature(self.hass, 30, ENTITY_NEST)
self.hass.block_till_done()
self.assertEqual('30.0', self.hass.states.get(ENTITY_NEST).state)
def test_set_away_mode_bad_attr(self):
"""Test setting the away mode without required attribute."""
state = self.hass.states.get(ENTITY_NEST)
self.assertEqual('off', state.attributes.get('away_mode'))
thermostat.set_away_mode(self.hass, None, ENTITY_NEST)
self.hass.block_till_done()
state = self.hass.states.get(ENTITY_NEST)
self.assertEqual('off', state.attributes.get('away_mode'))
def test_set_away_mode_on(self):
"""Test setting the away mode on/true."""
thermostat.set_away_mode(self.hass, True, ENTITY_NEST)
self.hass.block_till_done()
state = self.hass.states.get(ENTITY_NEST)
self.assertEqual('on', state.attributes.get('away_mode'))
def test_set_away_mode_off(self):
"""Test setting the away mode off/false."""
thermostat.set_away_mode(self.hass, False, ENTITY_NEST)
self.hass.block_till_done()
state = self.hass.states.get(ENTITY_NEST)
self.assertEqual('off', state.attributes.get('away_mode'))
def test_set_fan_mode_on_bad_attr(self):
"""Test setting the fan mode on/true without required attribute."""
state = self.hass.states.get(ENTITY_NEST)
self.assertEqual('off', state.attributes.get('fan'))
thermostat.set_fan_mode(self.hass, None, ENTITY_NEST)
self.hass.block_till_done()
state = self.hass.states.get(ENTITY_NEST)
self.assertEqual('off', state.attributes.get('fan'))
def test_set_fan_mode_on(self):
"""Test setting the fan mode on/true."""
thermostat.set_fan_mode(self.hass, True, ENTITY_NEST)
self.hass.block_till_done()
state = self.hass.states.get(ENTITY_NEST)
self.assertEqual('on', state.attributes.get('fan'))
def test_set_fan_mode_off(self):
"""Test setting the fan mode off/false."""
thermostat.set_fan_mode(self.hass, False, ENTITY_NEST)
self.hass.block_till_done()
state = self.hass.states.get(ENTITY_NEST)
self.assertEqual('off', state.attributes.get('fan'))

View File

@ -1,494 +0,0 @@
"""The tests for the heat control thermostat."""
import datetime
import unittest
from unittest import mock
from homeassistant.bootstrap import setup_component
from homeassistant.const import (
ATTR_UNIT_OF_MEASUREMENT,
SERVICE_TURN_OFF,
SERVICE_TURN_ON,
STATE_ON,
STATE_OFF,
TEMP_CELSIUS,
)
from homeassistant.util.unit_system import METRIC_SYSTEM
from homeassistant.components import thermostat
from tests.common import assert_setup_component, get_test_home_assistant
ENTITY = 'thermostat.test'
ENT_SENSOR = 'sensor.test'
ENT_SWITCH = 'switch.test'
MIN_TEMP = 3.0
MAX_TEMP = 65.0
TARGET_TEMP = 42.0
class TestSetupThermostatHeatControl(unittest.TestCase):
"""Test the Heat Control thermostat with custom config."""
def setUp(self): # pylint: disable=invalid-name
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
def tearDown(self): # pylint: disable=invalid-name
"""Stop down everything that was started."""
self.hass.stop()
def test_setup_missing_conf(self):
"""Test set up heat_control with missing config values."""
config = {
'name': 'test',
'target_sensor': ENT_SENSOR
}
with assert_setup_component(0):
setup_component(self.hass, 'thermostat', {
'thermostat': config})
def test_valid_conf(self):
"""Test set up heat_control with valid config values."""
self.assertTrue(setup_component(self.hass, 'thermostat',
{'thermostat': {
'platform': 'heat_control',
'name': 'test',
'heater': ENT_SWITCH,
'target_sensor': ENT_SENSOR}}))
def test_setup_with_sensor(self):
"""Test set up heat_control with sensor to trigger update at init."""
self.hass.states.set(ENT_SENSOR, 22.0, {
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS
})
thermostat.setup(self.hass, {'thermostat': {
'platform': 'heat_control',
'name': 'test',
'heater': ENT_SWITCH,
'target_sensor': ENT_SENSOR
}})
state = self.hass.states.get(ENTITY)
self.assertEqual(
TEMP_CELSIUS, state.attributes.get('unit_of_measurement'))
self.assertEqual(22.0, state.attributes.get('current_temperature'))
class TestThermostatHeatControl(unittest.TestCase):
"""Test the Heat Control thermostat."""
def setUp(self): # pylint: disable=invalid-name
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.units = METRIC_SYSTEM
thermostat.setup(self.hass, {'thermostat': {
'platform': 'heat_control',
'name': 'test',
'heater': ENT_SWITCH,
'target_sensor': ENT_SENSOR
}})
def tearDown(self): # pylint: disable=invalid-name
"""Stop down everything that was started."""
self.hass.stop()
def test_setup_defaults_to_unknown(self):
"""Test the setting of defaults to unknown."""
self.assertEqual('unknown', self.hass.states.get(ENTITY).state)
def test_default_setup_params(self):
"""Test the setup with default parameters."""
state = self.hass.states.get(ENTITY)
self.assertEqual(7, state.attributes.get('min_temp'))
self.assertEqual(35, state.attributes.get('max_temp'))
self.assertEqual(None, state.attributes.get('temperature'))
def test_custom_setup_params(self):
"""Test the setup with custom parameters."""
thermostat.setup(self.hass, {'thermostat': {
'platform': 'heat_control',
'name': 'test',
'heater': ENT_SWITCH,
'target_sensor': ENT_SENSOR,
'min_temp': MIN_TEMP,
'max_temp': MAX_TEMP,
'target_temp': TARGET_TEMP
}})
state = self.hass.states.get(ENTITY)
self.assertEqual(MIN_TEMP, state.attributes.get('min_temp'))
self.assertEqual(MAX_TEMP, state.attributes.get('max_temp'))
self.assertEqual(TARGET_TEMP, state.attributes.get('temperature'))
self.assertEqual(str(TARGET_TEMP), self.hass.states.get(ENTITY).state)
def test_set_target_temp(self):
"""Test the setting of the target temperature."""
thermostat.set_temperature(self.hass, 30)
self.hass.block_till_done()
self.assertEqual('30.0', self.hass.states.get(ENTITY).state)
def test_sensor_bad_unit(self):
"""Test sensor that have bad unit."""
state = self.hass.states.get(ENTITY)
temp = state.attributes.get('current_temperature')
unit = state.attributes.get('unit_of_measurement')
self._setup_sensor(22.0, unit='bad_unit')
self.hass.block_till_done()
state = self.hass.states.get(ENTITY)
self.assertEqual(unit, state.attributes.get('unit_of_measurement'))
self.assertEqual(temp, state.attributes.get('current_temperature'))
def test_sensor_bad_value(self):
"""Test sensor that have None as state."""
state = self.hass.states.get(ENTITY)
temp = state.attributes.get('current_temperature')
unit = state.attributes.get('unit_of_measurement')
self._setup_sensor(None)
self.hass.block_till_done()
state = self.hass.states.get(ENTITY)
self.assertEqual(unit, state.attributes.get('unit_of_measurement'))
self.assertEqual(temp, state.attributes.get('current_temperature'))
def test_set_target_temp_heater_on(self):
"""Test if target temperature turn heater on."""
self._setup_switch(False)
self._setup_sensor(25)
self.hass.block_till_done()
thermostat.set_temperature(self.hass, 30)
self.hass.block_till_done()
self.assertEqual(1, len(self.calls))
call = self.calls[0]
self.assertEqual('switch', call.domain)
self.assertEqual(SERVICE_TURN_ON, call.service)
self.assertEqual(ENT_SWITCH, call.data['entity_id'])
def test_set_target_temp_heater_off(self):
"""Test if target temperature turn heater off."""
self._setup_switch(True)
self._setup_sensor(30)
self.hass.block_till_done()
thermostat.set_temperature(self.hass, 25)
self.hass.block_till_done()
self.assertEqual(1, len(self.calls))
call = self.calls[0]
self.assertEqual('switch', call.domain)
self.assertEqual(SERVICE_TURN_OFF, call.service)
self.assertEqual(ENT_SWITCH, call.data['entity_id'])
def test_set_temp_change_heater_on(self):
"""Test if temperature change turn heater on."""
self._setup_switch(False)
thermostat.set_temperature(self.hass, 30)
self.hass.block_till_done()
self._setup_sensor(25)
self.hass.block_till_done()
self.assertEqual(1, len(self.calls))
call = self.calls[0]
self.assertEqual('switch', call.domain)
self.assertEqual(SERVICE_TURN_ON, call.service)
self.assertEqual(ENT_SWITCH, call.data['entity_id'])
def test_temp_change_heater_off(self):
"""Test if temperature change turn heater off."""
self._setup_switch(True)
thermostat.set_temperature(self.hass, 25)
self.hass.block_till_done()
self._setup_sensor(30)
self.hass.block_till_done()
self.assertEqual(1, len(self.calls))
call = self.calls[0]
self.assertEqual('switch', call.domain)
self.assertEqual(SERVICE_TURN_OFF, call.service)
self.assertEqual(ENT_SWITCH, call.data['entity_id'])
def _setup_sensor(self, temp, unit=TEMP_CELSIUS):
"""Setup the test sensor."""
self.hass.states.set(ENT_SENSOR, temp, {
ATTR_UNIT_OF_MEASUREMENT: unit
})
def _setup_switch(self, is_on):
"""Setup the test switch."""
self.hass.states.set(ENT_SWITCH, STATE_ON if is_on else STATE_OFF)
self.calls = []
def log_call(call):
"""Log service calls."""
self.calls.append(call)
self.hass.services.register('switch', SERVICE_TURN_ON, log_call)
self.hass.services.register('switch', SERVICE_TURN_OFF, log_call)
class TestThermostatHeatControlACMode(unittest.TestCase):
"""Test the Heat Control thermostat."""
def setUp(self): # pylint: disable=invalid-name
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.temperature_unit = TEMP_CELSIUS
thermostat.setup(self.hass, {'thermostat': {
'platform': 'heat_control',
'name': 'test',
'heater': ENT_SWITCH,
'target_sensor': ENT_SENSOR,
'ac_mode': True
}})
def tearDown(self): # pylint: disable=invalid-name
"""Stop down everything that was started."""
self.hass.stop()
def test_set_target_temp_ac_off(self):
"""Test if target temperature turn ac off."""
self._setup_switch(True)
self._setup_sensor(25)
self.hass.block_till_done()
thermostat.set_temperature(self.hass, 30)
self.hass.block_till_done()
self.assertEqual(1, len(self.calls))
call = self.calls[0]
self.assertEqual('switch', call.domain)
self.assertEqual(SERVICE_TURN_OFF, call.service)
self.assertEqual(ENT_SWITCH, call.data['entity_id'])
def test_set_target_temp_ac_on(self):
"""Test if target temperature turn ac on."""
self._setup_switch(False)
self._setup_sensor(30)
self.hass.block_till_done()
thermostat.set_temperature(self.hass, 25)
self.hass.block_till_done()
self.assertEqual(1, len(self.calls))
call = self.calls[0]
self.assertEqual('switch', call.domain)
self.assertEqual(SERVICE_TURN_ON, call.service)
self.assertEqual(ENT_SWITCH, call.data['entity_id'])
def test_set_temp_change_ac_off(self):
"""Test if temperature change turn ac off."""
self._setup_switch(True)
thermostat.set_temperature(self.hass, 30)
self.hass.block_till_done()
self._setup_sensor(25)
self.hass.block_till_done()
self.assertEqual(1, len(self.calls))
call = self.calls[0]
self.assertEqual('switch', call.domain)
self.assertEqual(SERVICE_TURN_OFF, call.service)
self.assertEqual(ENT_SWITCH, call.data['entity_id'])
def test_temp_change_ac_on(self):
"""Test if temperature change turn ac on."""
self._setup_switch(False)
thermostat.set_temperature(self.hass, 25)
self.hass.block_till_done()
self._setup_sensor(30)
self.hass.block_till_done()
self.assertEqual(1, len(self.calls))
call = self.calls[0]
self.assertEqual('switch', call.domain)
self.assertEqual(SERVICE_TURN_ON, call.service)
self.assertEqual(ENT_SWITCH, call.data['entity_id'])
def _setup_sensor(self, temp, unit=TEMP_CELSIUS):
"""Setup the test sensor."""
self.hass.states.set(ENT_SENSOR, temp, {
ATTR_UNIT_OF_MEASUREMENT: unit
})
def _setup_switch(self, is_on):
"""Setup the test switch."""
self.hass.states.set(ENT_SWITCH, STATE_ON if is_on else STATE_OFF)
self.calls = []
def log_call(call):
"""Log service calls."""
self.calls.append(call)
self.hass.services.register('switch', SERVICE_TURN_ON, log_call)
self.hass.services.register('switch', SERVICE_TURN_OFF, log_call)
class TestThermostatHeatControlACModeMinCycle(unittest.TestCase):
"""Test the Heat Control thermostat."""
def setUp(self): # pylint: disable=invalid-name
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.temperature_unit = TEMP_CELSIUS
thermostat.setup(self.hass, {'thermostat': {
'platform': 'heat_control',
'name': 'test',
'heater': ENT_SWITCH,
'target_sensor': ENT_SENSOR,
'ac_mode': True,
'min_cycle_duration': datetime.timedelta(minutes=10)
}})
def tearDown(self): # pylint: disable=invalid-name
"""Stop down everything that was started."""
self.hass.stop()
def test_temp_change_ac_trigger_on_not_long_enough(self):
"""Test if temperature change turn ac on."""
self._setup_switch(False)
thermostat.set_temperature(self.hass, 25)
self.hass.block_till_done()
self._setup_sensor(30)
self.hass.block_till_done()
self.assertEqual(0, len(self.calls))
def test_temp_change_ac_trigger_on_long_enough(self):
"""Test if temperature change turn ac on."""
fake_changed = datetime.datetime(1918, 11, 11, 11, 11, 11,
tzinfo=datetime.timezone.utc)
with mock.patch('homeassistant.helpers.condition.dt_util.utcnow',
return_value=fake_changed):
self._setup_switch(False)
thermostat.set_temperature(self.hass, 25)
self.hass.block_till_done()
self._setup_sensor(30)
self.hass.block_till_done()
self.assertEqual(1, len(self.calls))
call = self.calls[0]
self.assertEqual('switch', call.domain)
self.assertEqual(SERVICE_TURN_ON, call.service)
self.assertEqual(ENT_SWITCH, call.data['entity_id'])
def test_temp_change_ac_trigger_off_not_long_enough(self):
"""Test if temperature change turn ac on."""
self._setup_switch(True)
thermostat.set_temperature(self.hass, 30)
self.hass.block_till_done()
self._setup_sensor(25)
self.hass.block_till_done()
self.assertEqual(0, len(self.calls))
def test_temp_change_ac_trigger_off_long_enough(self):
"""Test if temperature change turn ac on."""
fake_changed = datetime.datetime(1918, 11, 11, 11, 11, 11,
tzinfo=datetime.timezone.utc)
with mock.patch('homeassistant.helpers.condition.dt_util.utcnow',
return_value=fake_changed):
self._setup_switch(True)
thermostat.set_temperature(self.hass, 30)
self.hass.block_till_done()
self._setup_sensor(25)
self.hass.block_till_done()
self.assertEqual(1, len(self.calls))
call = self.calls[0]
self.assertEqual('switch', call.domain)
self.assertEqual(SERVICE_TURN_OFF, call.service)
self.assertEqual(ENT_SWITCH, call.data['entity_id'])
def _setup_sensor(self, temp, unit=TEMP_CELSIUS):
"""Setup the test sensor."""
self.hass.states.set(ENT_SENSOR, temp, {
ATTR_UNIT_OF_MEASUREMENT: unit
})
def _setup_switch(self, is_on):
"""Setup the test switch."""
self.hass.states.set(ENT_SWITCH, STATE_ON if is_on else STATE_OFF)
self.calls = []
def log_call(call):
"""Log service calls."""
self.calls.append(call)
self.hass.services.register('switch', SERVICE_TURN_ON, log_call)
self.hass.services.register('switch', SERVICE_TURN_OFF, log_call)
class TestThermostatHeatControlMinCycle(unittest.TestCase):
"""Test the Heat Control thermostat."""
def setUp(self): # pylint: disable=invalid-name
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.temperature_unit = TEMP_CELSIUS
thermostat.setup(self.hass, {'thermostat': {
'platform': 'heat_control',
'name': 'test',
'heater': ENT_SWITCH,
'target_sensor': ENT_SENSOR,
'min_cycle_duration': datetime.timedelta(minutes=10)
}})
def tearDown(self): # pylint: disable=invalid-name
"""Stop down everything that was started."""
self.hass.stop()
def test_temp_change_heater_trigger_off_not_long_enough(self):
"""Test if temp change doesn't turn heater off because of time."""
self._setup_switch(True)
thermostat.set_temperature(self.hass, 25)
self.hass.block_till_done()
self._setup_sensor(30)
self.hass.block_till_done()
self.assertEqual(0, len(self.calls))
def test_temp_change_heater_trigger_on_not_long_enough(self):
"""Test if temp change doesn't turn heater on because of time."""
self._setup_switch(False)
thermostat.set_temperature(self.hass, 30)
self.hass.block_till_done()
self._setup_sensor(25)
self.hass.block_till_done()
self.assertEqual(0, len(self.calls))
def test_temp_change_heater_trigger_on_long_enough(self):
"""Test if temperature change turn heater on after min cycle."""
fake_changed = datetime.datetime(1918, 11, 11, 11, 11, 11,
tzinfo=datetime.timezone.utc)
with mock.patch('homeassistant.helpers.condition.dt_util.utcnow',
return_value=fake_changed):
self._setup_switch(False)
thermostat.set_temperature(self.hass, 30)
self.hass.block_till_done()
self._setup_sensor(25)
self.hass.block_till_done()
self.assertEqual(1, len(self.calls))
call = self.calls[0]
self.assertEqual('switch', call.domain)
self.assertEqual(SERVICE_TURN_ON, call.service)
self.assertEqual(ENT_SWITCH, call.data['entity_id'])
def test_temp_change_heater_trigger_off_long_enough(self):
"""Test if temperature change turn heater off after min cycle."""
fake_changed = datetime.datetime(1918, 11, 11, 11, 11, 11,
tzinfo=datetime.timezone.utc)
with mock.patch('homeassistant.helpers.condition.dt_util.utcnow',
return_value=fake_changed):
self._setup_switch(True)
thermostat.set_temperature(self.hass, 25)
self.hass.block_till_done()
self._setup_sensor(30)
self.hass.block_till_done()
self.assertEqual(1, len(self.calls))
call = self.calls[0]
self.assertEqual('switch', call.domain)
self.assertEqual(SERVICE_TURN_OFF, call.service)
self.assertEqual(ENT_SWITCH, call.data['entity_id'])
def _setup_sensor(self, temp, unit=TEMP_CELSIUS):
"""Setup the test sensor."""
self.hass.states.set(ENT_SENSOR, temp, {
ATTR_UNIT_OF_MEASUREMENT: unit
})
def _setup_switch(self, is_on):
"""Setup the test switch."""
self.hass.states.set(ENT_SWITCH, STATE_ON if is_on else STATE_OFF)
self.calls = []
def log_call(call):
"""Log service calls."""
self.calls.append(call)
self.hass.services.register('switch', SERVICE_TURN_ON, log_call)
self.hass.services.register('switch', SERVICE_TURN_OFF, log_call)

View File

@ -1,391 +0,0 @@
"""The test the Honeywell thermostat module."""
import socket
import unittest
from unittest import mock
import somecomfort
from homeassistant.const import (CONF_USERNAME, CONF_PASSWORD,
TEMP_CELSIUS, TEMP_FAHRENHEIT)
import homeassistant.components.thermostat.honeywell as honeywell
class TestHoneywell(unittest.TestCase):
"""A test class for Honeywell themostats."""
@mock.patch('somecomfort.SomeComfort')
@mock.patch('homeassistant.components.thermostat.'
'honeywell.HoneywellUSThermostat')
def test_setup_us(self, mock_ht, mock_sc):
"""Test for the US setup."""
config = {
CONF_USERNAME: 'user',
CONF_PASSWORD: 'pass',
'region': 'us',
}
bad_pass_config = {
CONF_USERNAME: 'user',
'region': 'us',
}
bad_region_config = {
CONF_USERNAME: 'user',
CONF_PASSWORD: 'pass',
'region': 'un',
}
hass = mock.MagicMock()
add_devices = mock.MagicMock()
locations = [
mock.MagicMock(),
mock.MagicMock(),
]
devices_1 = [mock.MagicMock()]
devices_2 = [mock.MagicMock(), mock.MagicMock]
mock_sc.return_value.locations_by_id.values.return_value = \
locations
locations[0].devices_by_id.values.return_value = devices_1
locations[1].devices_by_id.values.return_value = devices_2
result = honeywell.setup_platform(hass, bad_pass_config, add_devices)
self.assertFalse(result)
result = honeywell.setup_platform(hass, bad_region_config, add_devices)
self.assertFalse(result)
result = honeywell.setup_platform(hass, config, add_devices)
self.assertTrue(result)
self.assertEqual(mock_sc.call_count, 1)
self.assertEqual(mock_sc.call_args, mock.call('user', 'pass'))
mock_ht.assert_has_calls([
mock.call(mock_sc.return_value, devices_1[0]),
mock.call(mock_sc.return_value, devices_2[0]),
mock.call(mock_sc.return_value, devices_2[1]),
])
@mock.patch('somecomfort.SomeComfort')
def test_setup_us_failures(self, mock_sc):
"""Test the US setup."""
hass = mock.MagicMock()
add_devices = mock.MagicMock()
config = {
CONF_USERNAME: 'user',
CONF_PASSWORD: 'pass',
'region': 'us',
}
mock_sc.side_effect = somecomfort.AuthError
result = honeywell.setup_platform(hass, config, add_devices)
self.assertFalse(result)
self.assertFalse(add_devices.called)
mock_sc.side_effect = somecomfort.SomeComfortError
result = honeywell.setup_platform(hass, config, add_devices)
self.assertFalse(result)
self.assertFalse(add_devices.called)
@mock.patch('somecomfort.SomeComfort')
@mock.patch('homeassistant.components.thermostat.'
'honeywell.HoneywellUSThermostat')
def _test_us_filtered_devices(self, mock_ht, mock_sc, loc=None, dev=None):
"""Test for US filtered thermostats."""
config = {
CONF_USERNAME: 'user',
CONF_PASSWORD: 'pass',
'region': 'us',
'location': loc,
'thermostat': dev,
}
locations = {
1: mock.MagicMock(locationid=mock.sentinel.loc1,
devices_by_id={
11: mock.MagicMock(
deviceid=mock.sentinel.loc1dev1),
12: mock.MagicMock(
deviceid=mock.sentinel.loc1dev2),
}),
2: mock.MagicMock(locationid=mock.sentinel.loc2,
devices_by_id={
21: mock.MagicMock(
deviceid=mock.sentinel.loc2dev1),
}),
3: mock.MagicMock(locationid=mock.sentinel.loc3,
devices_by_id={
31: mock.MagicMock(
deviceid=mock.sentinel.loc3dev1),
}),
}
mock_sc.return_value = mock.MagicMock(locations_by_id=locations)
hass = mock.MagicMock()
add_devices = mock.MagicMock()
self.assertEqual(True,
honeywell.setup_platform(hass, config, add_devices))
return mock_ht.call_args_list, mock_sc
def test_us_filtered_thermostat_1(self):
"""Test for US filtered thermostats."""
result, client = self._test_us_filtered_devices(
dev=mock.sentinel.loc1dev1)
devices = [x[0][1].deviceid for x in result]
self.assertEqual([mock.sentinel.loc1dev1], devices)
def test_us_filtered_thermostat_2(self):
"""Test for US filtered location."""
result, client = self._test_us_filtered_devices(
dev=mock.sentinel.loc2dev1)
devices = [x[0][1].deviceid for x in result]
self.assertEqual([mock.sentinel.loc2dev1], devices)
def test_us_filtered_location_1(self):
"""Test for US filtered locations."""
result, client = self._test_us_filtered_devices(
loc=mock.sentinel.loc1)
devices = [x[0][1].deviceid for x in result]
self.assertEqual([mock.sentinel.loc1dev1,
mock.sentinel.loc1dev2], devices)
def test_us_filtered_location_2(self):
"""Test for US filtered locations."""
result, client = self._test_us_filtered_devices(
loc=mock.sentinel.loc2)
devices = [x[0][1].deviceid for x in result]
self.assertEqual([mock.sentinel.loc2dev1], devices)
@mock.patch('evohomeclient.EvohomeClient')
@mock.patch('homeassistant.components.thermostat.honeywell.'
'RoundThermostat')
def test_eu_setup_full_config(self, mock_round, mock_evo):
"""Test the EU setup wwith complete configuration."""
config = {
CONF_USERNAME: 'user',
CONF_PASSWORD: 'pass',
honeywell.CONF_AWAY_TEMP: 20,
'region': 'eu',
}
mock_evo.return_value.temperatures.return_value = [
{'id': 'foo'}, {'id': 'bar'}]
hass = mock.MagicMock()
add_devices = mock.MagicMock()
self.assertTrue(honeywell.setup_platform(hass, config, add_devices))
self.assertEqual(mock_evo.call_count, 1)
self.assertEqual(mock_evo.call_args, mock.call('user', 'pass'))
self.assertEqual(mock_evo.return_value.temperatures.call_count, 1)
self.assertEqual(
mock_evo.return_value.temperatures.call_args,
mock.call(force_refresh=True)
)
mock_round.assert_has_calls([
mock.call(mock_evo.return_value, 'foo', True, 20),
mock.call(mock_evo.return_value, 'bar', False, 20),
])
self.assertEqual(2, add_devices.call_count)
@mock.patch('evohomeclient.EvohomeClient')
@mock.patch('homeassistant.components.thermostat.honeywell.'
'RoundThermostat')
def test_eu_setup_partial_config(self, mock_round, mock_evo):
"""Test the EU setup with partial configuration."""
config = {
CONF_USERNAME: 'user',
CONF_PASSWORD: 'pass',
'region': 'eu',
}
mock_evo.return_value.temperatures.return_value = [
{'id': 'foo'}, {'id': 'bar'}]
hass = mock.MagicMock()
add_devices = mock.MagicMock()
self.assertTrue(honeywell.setup_platform(hass, config, add_devices))
default = honeywell.DEFAULT_AWAY_TEMP
mock_round.assert_has_calls([
mock.call(mock_evo.return_value, 'foo', True, default),
mock.call(mock_evo.return_value, 'bar', False, default),
])
@mock.patch('evohomeclient.EvohomeClient')
@mock.patch('homeassistant.components.thermostat.honeywell.'
'RoundThermostat')
def test_eu_setup_bad_temp(self, mock_round, mock_evo):
"""Test the EU setup with invalid temperature."""
config = {
CONF_USERNAME: 'user',
CONF_PASSWORD: 'pass',
honeywell.CONF_AWAY_TEMP: 'ponies',
'region': 'eu',
}
self.assertFalse(honeywell.setup_platform(None, config, None))
@mock.patch('evohomeclient.EvohomeClient')
@mock.patch('homeassistant.components.thermostat.honeywell.'
'RoundThermostat')
def test_eu_setup_error(self, mock_round, mock_evo):
"""Test the EU setup with errors."""
config = {
CONF_USERNAME: 'user',
CONF_PASSWORD: 'pass',
honeywell.CONF_AWAY_TEMP: 20,
'region': 'eu',
}
mock_evo.return_value.temperatures.side_effect = socket.error
add_devices = mock.MagicMock()
hass = mock.MagicMock()
self.assertFalse(honeywell.setup_platform(hass, config, add_devices))
class TestHoneywellRound(unittest.TestCase):
"""A test class for Honeywell Round thermostats."""
def setup_method(self, method):
"""Test the setup method."""
def fake_temperatures(force_refresh=None):
"""Create fake temperatures."""
temps = [
{'id': '1', 'temp': 20, 'setpoint': 21,
'thermostat': 'main', 'name': 'House'},
{'id': '2', 'temp': 21, 'setpoint': 22,
'thermostat': 'DOMESTIC_HOT_WATER'},
]
return temps
self.device = mock.MagicMock()
self.device.temperatures.side_effect = fake_temperatures
self.round1 = honeywell.RoundThermostat(self.device, '1',
True, 16)
self.round2 = honeywell.RoundThermostat(self.device, '2',
False, 17)
def test_attributes(self):
"""Test the attributes."""
self.assertEqual('House', self.round1.name)
self.assertEqual(TEMP_CELSIUS, self.round1.unit_of_measurement)
self.assertEqual(20, self.round1.current_temperature)
self.assertEqual(21, self.round1.target_temperature)
self.assertFalse(self.round1.is_away_mode_on)
self.assertEqual('Hot Water', self.round2.name)
self.assertEqual(TEMP_CELSIUS, self.round2.unit_of_measurement)
self.assertEqual(21, self.round2.current_temperature)
self.assertEqual(None, self.round2.target_temperature)
self.assertFalse(self.round2.is_away_mode_on)
def test_away_mode(self):
"""Test setting the away mode."""
self.assertFalse(self.round1.is_away_mode_on)
self.round1.turn_away_mode_on()
self.assertTrue(self.round1.is_away_mode_on)
self.assertEqual(self.device.set_temperature.call_count, 1)
self.assertEqual(
self.device.set_temperature.call_args, mock.call('House', 16)
)
self.device.set_temperature.reset_mock()
self.round1.turn_away_mode_off()
self.assertFalse(self.round1.is_away_mode_on)
self.assertEqual(self.device.cancel_temp_override.call_count, 1)
self.assertEqual(
self.device.cancel_temp_override.call_args, mock.call('House')
)
def test_set_temperature(self):
"""Test setting the temperature."""
self.round1.set_temperature(25)
self.assertEqual(self.device.set_temperature.call_count, 1)
self.assertEqual(
self.device.set_temperature.call_args, mock.call('House', 25)
)
def test_set_hvac_mode(self: unittest.TestCase) -> None:
"""Test setting the system operation."""
self.round1.set_hvac_mode('cool')
self.assertEqual('cool', self.round1.operation)
self.assertEqual('cool', self.device.system_mode)
self.round1.set_hvac_mode('heat')
self.assertEqual('heat', self.round1.operation)
self.assertEqual('heat', self.device.system_mode)
class TestHoneywellUS(unittest.TestCase):
"""A test class for Honeywell US thermostats."""
def setup_method(self, method):
"""Test the setup method."""
self.client = mock.MagicMock()
self.device = mock.MagicMock()
self.honeywell = honeywell.HoneywellUSThermostat(
self.client, self.device)
self.device.fan_running = True
self.device.name = 'test'
self.device.temperature_unit = 'F'
self.device.current_temperature = 72
self.device.setpoint_cool = 78
self.device.setpoint_heat = 65
self.device.system_mode = 'heat'
self.device.fan_mode = 'auto'
def test_properties(self):
"""Test the properties."""
self.assertTrue(self.honeywell.is_fan_on)
self.assertEqual('test', self.honeywell.name)
self.assertEqual(72, self.honeywell.current_temperature)
def test_unit_of_measurement(self):
"""Test the unit of measurement."""
self.assertEqual(TEMP_FAHRENHEIT, self.honeywell.unit_of_measurement)
self.device.temperature_unit = 'C'
self.assertEqual(TEMP_CELSIUS, self.honeywell.unit_of_measurement)
def test_target_temp(self):
"""Test the target temperature."""
self.assertEqual(65, self.honeywell.target_temperature)
self.device.system_mode = 'cool'
self.assertEqual(78, self.honeywell.target_temperature)
def test_set_temp(self):
"""Test setting the temperature."""
self.honeywell.set_temperature(70)
self.assertEqual(70, self.device.setpoint_heat)
self.assertEqual(70, self.honeywell.target_temperature)
self.device.system_mode = 'cool'
self.assertEqual(78, self.honeywell.target_temperature)
self.honeywell.set_temperature(74)
self.assertEqual(74, self.device.setpoint_cool)
self.assertEqual(74, self.honeywell.target_temperature)
def test_set_hvac_mode(self: unittest.TestCase) -> None:
"""Test setting the HVAC mode."""
self.honeywell.set_hvac_mode('cool')
self.assertEqual('cool', self.honeywell.operation)
self.assertEqual('cool', self.device.system_mode)
self.honeywell.set_hvac_mode('heat')
self.assertEqual('heat', self.honeywell.operation)
self.assertEqual('heat', self.device.system_mode)
def test_set_temp_fail(self):
"""Test if setting the temperature fails."""
self.device.setpoint_heat = mock.MagicMock(
side_effect=somecomfort.SomeComfortError)
self.honeywell.set_temperature(123)
def test_attributes(self):
"""Test the attributes."""
expected = {
'fan': 'running',
'fanmode': 'auto',
'system_mode': 'heat',
}
self.assertEqual(expected, self.honeywell.device_state_attributes)
expected['fan'] = 'idle'
self.device.fan_running = False
self.assertEqual(expected, self.honeywell.device_state_attributes)
def test_with_no_fan(self):
"""Test if there is on fan."""
self.device.fan_running = False
self.device.fan_mode = None
expected = {
'fan': 'idle',
'fanmode': None,
'system_mode': 'heat',
}
self.assertEqual(expected, self.honeywell.device_state_attributes)