mirror of
https://github.com/home-assistant/core.git
synced 2025-07-25 14:17:45 +00:00
1) Performed many pylint and flake8 fixes to clean up isy994 integration and hidden entities addition. 2) Added necessary code to allow groups to also be hidden. 3) Made most of the weather data from the isy994 component be hidden by default.
This commit is contained in:
parent
caed69d5ea
commit
b20424261c
@ -625,8 +625,8 @@ class StateMachine(object):
|
|||||||
# components that don't use the Entity base class for their entities.
|
# components that don't use the Entity base class for their entities.
|
||||||
# The sun component is an example of this. The Entity class cannot be
|
# The sun component is an example of this. The Entity class cannot be
|
||||||
# imported cleanly, so assume the state is shown. This means that for
|
# imported cleanly, so assume the state is shown. This means that for
|
||||||
# visibility to be supported, the state must originate from a class that
|
# visibility to be supported, the state must originate from a class
|
||||||
# uses the base class Entity or it must manually put the hidden
|
# that uses the base class Entity or it must manually put the hidden
|
||||||
# attribute in its attributes dictionary.
|
# attribute in its attributes dictionary.
|
||||||
if ATTR_HIDDEN not in attributes:
|
if ATTR_HIDDEN not in attributes:
|
||||||
attributes[ATTR_HIDDEN] = False
|
attributes[ATTR_HIDDEN] = False
|
||||||
|
@ -208,7 +208,7 @@ def process_ha_core_config(hass, config):
|
|||||||
if key in config:
|
if key in config:
|
||||||
setattr(hass.config, attr, config[key])
|
setattr(hass.config, attr, config[key])
|
||||||
|
|
||||||
Entity._visibility.update(config.get('visibility', [{}])[0])
|
Entity.visibility.update(config.get('visibility', [{}])[0])
|
||||||
|
|
||||||
if CONF_TEMPERATURE_UNIT in config:
|
if CONF_TEMPERATURE_UNIT in config:
|
||||||
unit = config[CONF_TEMPERATURE_UNIT]
|
unit = config[CONF_TEMPERATURE_UNIT]
|
||||||
|
@ -7,10 +7,11 @@ Provides functionality to group devices that can be turned on or off.
|
|||||||
|
|
||||||
import homeassistant as ha
|
import homeassistant as ha
|
||||||
from homeassistant.helpers import generate_entity_id
|
from homeassistant.helpers import generate_entity_id
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
import homeassistant.util as util
|
import homeassistant.util as util
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID, ATTR_FRIENDLY_NAME, STATE_ON, STATE_OFF,
|
ATTR_ENTITY_ID, ATTR_FRIENDLY_NAME, STATE_ON, STATE_OFF,
|
||||||
STATE_HOME, STATE_NOT_HOME, STATE_UNKNOWN)
|
STATE_HOME, STATE_NOT_HOME, STATE_UNKNOWN, ATTR_HIDDEN)
|
||||||
|
|
||||||
DOMAIN = "group"
|
DOMAIN = "group"
|
||||||
DEPENDENCIES = []
|
DEPENDENCIES = []
|
||||||
@ -112,6 +113,10 @@ def setup(hass, config):
|
|||||||
|
|
||||||
class Group(object):
|
class Group(object):
|
||||||
""" Tracks a group of entity ids. """
|
""" Tracks a group of entity ids. """
|
||||||
|
|
||||||
|
visibility = Entity.visibility
|
||||||
|
_hidden = False
|
||||||
|
|
||||||
def __init__(self, hass, name, entity_ids=None, user_defined=True):
|
def __init__(self, hass, name, entity_ids=None, user_defined=True):
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -138,7 +143,8 @@ class Group(object):
|
|||||||
return {
|
return {
|
||||||
ATTR_ENTITY_ID: self.tracking,
|
ATTR_ENTITY_ID: self.tracking,
|
||||||
ATTR_AUTO: not self.user_defined,
|
ATTR_AUTO: not self.user_defined,
|
||||||
ATTR_FRIENDLY_NAME: self.name
|
ATTR_FRIENDLY_NAME: self.name,
|
||||||
|
ATTR_HIDDEN: self.hidden
|
||||||
}
|
}
|
||||||
|
|
||||||
def update_tracked_entity_ids(self, entity_ids):
|
def update_tracked_entity_ids(self, entity_ids):
|
||||||
@ -213,6 +219,24 @@ class Group(object):
|
|||||||
self.hass.states.set(
|
self.hass.states.set(
|
||||||
self.entity_id, group_off, self.state_attr)
|
self.entity_id, group_off, self.state_attr)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def hidden(self):
|
||||||
|
"""
|
||||||
|
Returns the official decision of whether the entity should be hidden.
|
||||||
|
Any value set by the user in the configuration file will overwrite
|
||||||
|
whatever the component sets for visibility.
|
||||||
|
"""
|
||||||
|
if self.entity_id is not None and \
|
||||||
|
self.entity_id.lower() in self.visibility:
|
||||||
|
return self.visibility[self.entity_id.lower()] == 'hide'
|
||||||
|
else:
|
||||||
|
return self._hidden
|
||||||
|
|
||||||
|
@hidden.setter
|
||||||
|
def hidden(self, val):
|
||||||
|
""" Sets the suggestion for visibility. """
|
||||||
|
self._hidden = bool(val)
|
||||||
|
|
||||||
|
|
||||||
def setup_group(hass, name, entity_ids, user_defined=True):
|
def setup_group(hass, name, entity_ids, user_defined=True):
|
||||||
""" Sets up a group state that is the combined state of
|
""" Sets up a group state that is the combined state of
|
||||||
|
@ -29,15 +29,19 @@ SENSOR_STRING = 'Sensor'
|
|||||||
HIDDEN_STRING = '{HIDE ME}'
|
HIDDEN_STRING = '{HIDE ME}'
|
||||||
|
|
||||||
# setup logger
|
# setup logger
|
||||||
logger = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
logger.setLevel(logging.DEBUG)
|
|
||||||
|
|
||||||
|
|
||||||
def setup(hass, config):
|
def setup(hass, config):
|
||||||
|
"""
|
||||||
|
Setup isy994 component.
|
||||||
|
This will automatically import associated lights, switches, and sensors.
|
||||||
|
"""
|
||||||
|
# pylint: disable=global-statement
|
||||||
# check for required values in configuration file
|
# check for required values in configuration file
|
||||||
if not validate_config(config,
|
if not validate_config(config,
|
||||||
{DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]},
|
{DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]},
|
||||||
logger):
|
_LOGGER):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# pull and parse standard configuration
|
# pull and parse standard configuration
|
||||||
@ -52,7 +56,7 @@ def setup(hass, config):
|
|||||||
addr = addr.replace('https://', '')
|
addr = addr.replace('https://', '')
|
||||||
https = True
|
https = True
|
||||||
else:
|
else:
|
||||||
logger.error('isy994 host value in configuration file is invalid.')
|
_LOGGER.error('isy994 host value in configuration file is invalid.')
|
||||||
return False
|
return False
|
||||||
port = host.port
|
port = host.port
|
||||||
addr = addr.replace(':{}'.format(port), '')
|
addr = addr.replace(':{}'.format(port), '')
|
||||||
@ -65,7 +69,7 @@ def setup(hass, config):
|
|||||||
|
|
||||||
# connect to ISY controller
|
# connect to ISY controller
|
||||||
global ISY
|
global ISY
|
||||||
ISY = PyISY.ISY(addr, port, user, password, use_https=https, log=logger)
|
ISY = PyISY.ISY(addr, port, user, password, use_https=https, log=_LOGGER)
|
||||||
if not ISY.connected:
|
if not ISY.connected:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -91,6 +95,7 @@ class ISYDeviceABC(ToggleEntity):
|
|||||||
_states = []
|
_states = []
|
||||||
_dtype = None
|
_dtype = None
|
||||||
_domain = None
|
_domain = None
|
||||||
|
_name = None
|
||||||
|
|
||||||
def __init__(self, node):
|
def __init__(self, node):
|
||||||
# setup properties
|
# setup properties
|
||||||
@ -98,34 +103,39 @@ class ISYDeviceABC(ToggleEntity):
|
|||||||
self.hidden = HIDDEN_STRING in self.raw_name
|
self.hidden = HIDDEN_STRING in self.raw_name
|
||||||
|
|
||||||
# track changes
|
# track changes
|
||||||
self._changeHandler = self.node.status. \
|
self._change_handler = self.node.status. \
|
||||||
subscribe('changed', self.onUpdate)
|
subscribe('changed', self.on_update)
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
""" cleanup subscriptions because it is the right thing to do. """
|
""" cleanup subscriptions because it is the right thing to do. """
|
||||||
self._changeHandler.unsubscribe()
|
self._change_handler.unsubscribe()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def domain(self):
|
def domain(self):
|
||||||
|
""" Returns the domain of the entity. """
|
||||||
return self._domain
|
return self._domain
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def dtype(self):
|
def dtype(self):
|
||||||
|
""" Returns the data type of the entity (binary or analog). """
|
||||||
if self._dtype in ['analog', 'binary']:
|
if self._dtype in ['analog', 'binary']:
|
||||||
return self._dtype
|
return self._dtype
|
||||||
return 'binary' if self._units is None else 'analog'
|
return 'binary' if self.unit_of_measurement is None else 'analog'
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def should_poll(self):
|
def should_poll(self):
|
||||||
|
""" Tells Home Assistant not to poll this entity. """
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self):
|
def value(self):
|
||||||
""" returns the unclean value from the controller """
|
""" returns the unclean value from the controller """
|
||||||
|
# pylint: disable=protected-access
|
||||||
return self.node.status._val
|
return self.node.status._val
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state_attributes(self):
|
def state_attributes(self):
|
||||||
|
""" Returns the state attributes for the node. """
|
||||||
attr = {ATTR_FRIENDLY_NAME: self.name}
|
attr = {ATTR_FRIENDLY_NAME: self.name}
|
||||||
for name, prop in self._attrs.items():
|
for name, prop in self._attrs.items():
|
||||||
attr[name] = getattr(self, prop)
|
attr[name] = getattr(self, prop)
|
||||||
@ -134,18 +144,18 @@ class ISYDeviceABC(ToggleEntity):
|
|||||||
@property
|
@property
|
||||||
def unique_id(self):
|
def unique_id(self):
|
||||||
""" Returns the id of this isy sensor """
|
""" Returns the id of this isy sensor """
|
||||||
|
# pylint: disable=protected-access
|
||||||
return self.node._id
|
return self.node._id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def raw_name(self):
|
def raw_name(self):
|
||||||
try:
|
""" Returns the unclean node name. """
|
||||||
return str(self._name)
|
return str(self._name) \
|
||||||
except AttributeError:
|
if self._name is not None else str(self.node.name)
|
||||||
return str(self.node.name)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
""" Returns the name of the node if any. """
|
""" Returns the cleaned name of the node. """
|
||||||
return self.raw_name.replace(HIDDEN_STRING, '').strip()
|
return self.raw_name.replace(HIDDEN_STRING, '').strip()
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
@ -153,16 +163,18 @@ class ISYDeviceABC(ToggleEntity):
|
|||||||
# ISY objects are automatically updated by the ISY's event stream
|
# ISY objects are automatically updated by the ISY's event stream
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def onUpdate(self, e):
|
def on_update(self, event):
|
||||||
""" Handles the update received event. """
|
""" Handles the update received event. """
|
||||||
self.update_ha_state()
|
self.update_ha_state()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self):
|
def is_on(self):
|
||||||
|
""" Returns boolean response if the node is on. """
|
||||||
return bool(self.value)
|
return bool(self.value)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_open(self):
|
def is_open(self):
|
||||||
|
""" Returns boolean respons if the node is open. On = Open. """
|
||||||
return self.is_on
|
return self.is_on
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -178,17 +190,18 @@ class ISYDeviceABC(ToggleEntity):
|
|||||||
attrs = [kwargs.get(name) for name in self._onattrs]
|
attrs = [kwargs.get(name) for name in self._onattrs]
|
||||||
self.node.on(*attrs)
|
self.node.on(*attrs)
|
||||||
else:
|
else:
|
||||||
logger.error('ISY cannot turn on sensors.')
|
_LOGGER.error('ISY cannot turn on sensors.')
|
||||||
|
|
||||||
def turn_off(self, **kwargs):
|
def turn_off(self, **kwargs):
|
||||||
""" turns the device off """
|
""" turns the device off """
|
||||||
if self.domain is not 'sensor':
|
if self.domain is not 'sensor':
|
||||||
self.node.off()
|
self.node.off()
|
||||||
else:
|
else:
|
||||||
logger.error('ISY cannot turn off sensors.')
|
_LOGGER.error('ISY cannot turn off sensors.')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unit_of_measurement(self):
|
def unit_of_measurement(self):
|
||||||
|
""" Returns the defined units of measurement or None. """
|
||||||
try:
|
try:
|
||||||
return self.node.units
|
return self.node.units
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
|
@ -3,13 +3,29 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
# homeassistant imports
|
# homeassistant imports
|
||||||
from homeassistant.components.isy994 import ISY, ISYDeviceABC, SENSOR_STRING
|
from homeassistant.components.isy994 import (ISY, ISYDeviceABC, SENSOR_STRING,
|
||||||
|
HIDDEN_STRING)
|
||||||
from homeassistant.const import (STATE_OPEN, STATE_CLOSED, STATE_HOME,
|
from homeassistant.const import (STATE_OPEN, STATE_CLOSED, STATE_HOME,
|
||||||
STATE_NOT_HOME, STATE_ON, STATE_OFF)
|
STATE_NOT_HOME, STATE_ON, STATE_OFF)
|
||||||
|
|
||||||
|
DEFAULT_HIDDEN_WEATHER = ['Temperature_High', 'Temperature_Low', 'Feels_Like',
|
||||||
|
'Temperature_Average', 'Pressure', 'Dew_Point',
|
||||||
|
'Gust_Speed', 'Evapotranspiration',
|
||||||
|
'Irrigation_Requirement', 'Water_Deficit_Yesterday',
|
||||||
|
'Elevation', 'Average_Temperature_Tomorrow',
|
||||||
|
'High_Temperature_Tomorrow',
|
||||||
|
'Low_Temperature_Tomorrow', 'Humidity_Tomorrow',
|
||||||
|
'Wind_Speed_Tomorrow', 'Gust_Speed_Tomorrow',
|
||||||
|
'Rain_Tomorrow', 'Snow_Tomorrow',
|
||||||
|
'Forecast_Average_Temperature',
|
||||||
|
'Forecast_High_Temperature',
|
||||||
|
'Forecast_Low_Temperature', 'Forecast_Humidity',
|
||||||
|
'Forecast_Rain', 'Forecast_Snow']
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
""" Sets up the isy994 platform. """
|
""" Sets up the isy994 platform. """
|
||||||
|
# pylint: disable=protected-access
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
devs = []
|
devs = []
|
||||||
# verify connection
|
# verify connection
|
||||||
@ -21,7 +37,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
|||||||
if ISY.climate is not None:
|
if ISY.climate is not None:
|
||||||
for prop in ISY.climate._id2name:
|
for prop in ISY.climate._id2name:
|
||||||
if prop is not None:
|
if prop is not None:
|
||||||
node = WeatherPseudoNode('ISY.weather.' + prop, prop,
|
prefix = HIDDEN_STRING if prop in DEFAULT_HIDDEN_WEATHER else ''
|
||||||
|
node = WeatherPseudoNode('ISY.weather.' + prop, prefix + prop,
|
||||||
getattr(ISY.climate, prop),
|
getattr(ISY.climate, prop),
|
||||||
getattr(ISY.climate, prop + '_units'))
|
getattr(ISY.climate, prop + '_units'))
|
||||||
devs.append(ISYSensorDevice(node))
|
devs.append(ISYSensorDevice(node))
|
||||||
@ -42,7 +59,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
|||||||
# folder does not exist
|
# folder does not exist
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
for dtype, name, node_id in folder.children:
|
for _, _, node_id in folder.children:
|
||||||
node = folder[node_id].leaf
|
node = folder[node_id].leaf
|
||||||
devs.append(ISYSensorDevice(node, states))
|
devs.append(ISYSensorDevice(node, states))
|
||||||
|
|
||||||
@ -51,6 +68,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
|||||||
|
|
||||||
class WeatherPseudoNode(object):
|
class WeatherPseudoNode(object):
|
||||||
""" This class allows weather variable to act as regular nodes. """
|
""" This class allows weather variable to act as regular nodes. """
|
||||||
|
# pylint: disable=too-few-public-methods
|
||||||
|
|
||||||
def __init__(self, device_id, name, status, units=None):
|
def __init__(self, device_id, name, status, units=None):
|
||||||
self._id = device_id
|
self._id = device_id
|
||||||
@ -64,6 +82,6 @@ class ISYSensorDevice(ISYDeviceABC):
|
|||||||
|
|
||||||
_domain = 'sensor'
|
_domain = 'sensor'
|
||||||
|
|
||||||
def __init__(self, node, states=[]):
|
def __init__(self, node, states=None):
|
||||||
super().__init__(node)
|
super().__init__(node)
|
||||||
self._states = states
|
self._states = states or []
|
||||||
|
@ -83,7 +83,7 @@ class Entity(object):
|
|||||||
|
|
||||||
hass = None
|
hass = None
|
||||||
entity_id = None
|
entity_id = None
|
||||||
_visibility = {}
|
visibility = {}
|
||||||
|
|
||||||
def update_ha_state(self, force_refresh=False):
|
def update_ha_state(self, force_refresh=False):
|
||||||
"""
|
"""
|
||||||
@ -138,8 +138,8 @@ class Entity(object):
|
|||||||
whatever the component sets for visibility.
|
whatever the component sets for visibility.
|
||||||
"""
|
"""
|
||||||
if self.entity_id is not None and \
|
if self.entity_id is not None and \
|
||||||
self.entity_id.lower() in self._visibility:
|
self.entity_id.lower() in self.visibility:
|
||||||
return self._visibility[self.entity_id.lower()] == 'hide'
|
return self.visibility[self.entity_id.lower()] == 'hide'
|
||||||
else:
|
else:
|
||||||
return self._hidden
|
return self._hidden
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user