mirror of
https://github.com/home-assistant/core.git
synced 2025-07-10 23:07:09 +00:00
Merge branch 'dev' into upgrade-sphinx
This commit is contained in:
commit
3bc83920b4
@ -18,7 +18,7 @@ from homeassistant.util.async_ import run_coroutine_threadsafe
|
|||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
from homeassistant.components.camera import async_get_still_stream
|
from homeassistant.components.camera import async_get_still_stream
|
||||||
|
|
||||||
REQUIREMENTS = ['pillow==5.2.0']
|
REQUIREMENTS = ['pillow==5.3.0']
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ from homeassistant.components.device_tracker import (
|
|||||||
DOMAIN, PLATFORM_SCHEMA, DeviceScanner)
|
DOMAIN, PLATFORM_SCHEMA, DeviceScanner)
|
||||||
from homeassistant.const import CONF_HOST
|
from homeassistant.const import CONF_HOST
|
||||||
|
|
||||||
REQUIREMENTS = ['ghlocalapi==0.1.0']
|
REQUIREMENTS = ['ghlocalapi==0.3.5']
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -89,4 +89,5 @@ class GoogleHomeDeviceScanner(DeviceScanner):
|
|||||||
devices[uuid]['btle_mac_address'] = device['mac_address']
|
devices[uuid]['btle_mac_address'] = device['mac_address']
|
||||||
devices[uuid]['ghname'] = ghname
|
devices[uuid]['ghname'] = ghname
|
||||||
devices[uuid]['source_type'] = 'bluetooth'
|
devices[uuid]['source_type'] = 'bluetooth'
|
||||||
|
await self.scanner.clear_scan_result()
|
||||||
self.last_results = devices
|
self.last_results = devices
|
||||||
|
@ -117,23 +117,19 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
|
|||||||
|
|
||||||
def __init__(self, config, discovery_hash):
|
def __init__(self, config, discovery_hash):
|
||||||
"""Initialize the MQTT fan."""
|
"""Initialize the MQTT fan."""
|
||||||
|
self._unique_id = config.get(CONF_UNIQUE_ID)
|
||||||
self._state = False
|
self._state = False
|
||||||
self._speed = None
|
self._speed = None
|
||||||
self._oscillation = None
|
self._oscillation = None
|
||||||
self._supported_features = 0
|
self._supported_features = 0
|
||||||
self._sub_state = None
|
self._sub_state = None
|
||||||
|
|
||||||
self._name = None
|
|
||||||
self._topic = None
|
self._topic = None
|
||||||
self._qos = None
|
|
||||||
self._retain = None
|
|
||||||
self._payload = None
|
self._payload = None
|
||||||
self._templates = None
|
self._templates = None
|
||||||
self._speed_list = None
|
|
||||||
self._optimistic = None
|
self._optimistic = None
|
||||||
self._optimistic_oscillation = None
|
self._optimistic_oscillation = None
|
||||||
self._optimistic_speed = None
|
self._optimistic_speed = None
|
||||||
self._unique_id = None
|
|
||||||
|
|
||||||
# Load config
|
# Load config
|
||||||
self._setup_from_config(config)
|
self._setup_from_config(config)
|
||||||
@ -141,9 +137,10 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
|
|||||||
availability_topic = config.get(CONF_AVAILABILITY_TOPIC)
|
availability_topic = config.get(CONF_AVAILABILITY_TOPIC)
|
||||||
payload_available = config.get(CONF_PAYLOAD_AVAILABLE)
|
payload_available = config.get(CONF_PAYLOAD_AVAILABLE)
|
||||||
payload_not_available = config.get(CONF_PAYLOAD_NOT_AVAILABLE)
|
payload_not_available = config.get(CONF_PAYLOAD_NOT_AVAILABLE)
|
||||||
|
qos = config.get(CONF_QOS)
|
||||||
device_config = config.get(CONF_DEVICE)
|
device_config = config.get(CONF_DEVICE)
|
||||||
|
|
||||||
MqttAvailability.__init__(self, availability_topic, self._qos,
|
MqttAvailability.__init__(self, availability_topic, qos,
|
||||||
payload_available, payload_not_available)
|
payload_available, payload_not_available)
|
||||||
MqttDiscoveryUpdate.__init__(self, discovery_hash,
|
MqttDiscoveryUpdate.__init__(self, discovery_hash,
|
||||||
self.discovery_update)
|
self.discovery_update)
|
||||||
@ -164,7 +161,7 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
|
|||||||
|
|
||||||
def _setup_from_config(self, config):
|
def _setup_from_config(self, config):
|
||||||
"""(Re)Setup the entity."""
|
"""(Re)Setup the entity."""
|
||||||
self._name = config.get(CONF_NAME)
|
self._config = config
|
||||||
self._topic = {
|
self._topic = {
|
||||||
key: config.get(key) for key in (
|
key: config.get(key) for key in (
|
||||||
CONF_STATE_TOPIC,
|
CONF_STATE_TOPIC,
|
||||||
@ -180,8 +177,6 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
|
|||||||
ATTR_SPEED: config.get(CONF_SPEED_VALUE_TEMPLATE),
|
ATTR_SPEED: config.get(CONF_SPEED_VALUE_TEMPLATE),
|
||||||
OSCILLATION: config.get(CONF_OSCILLATION_VALUE_TEMPLATE)
|
OSCILLATION: config.get(CONF_OSCILLATION_VALUE_TEMPLATE)
|
||||||
}
|
}
|
||||||
self._qos = config.get(CONF_QOS)
|
|
||||||
self._retain = config.get(CONF_RETAIN)
|
|
||||||
self._payload = {
|
self._payload = {
|
||||||
STATE_ON: config.get(CONF_PAYLOAD_ON),
|
STATE_ON: config.get(CONF_PAYLOAD_ON),
|
||||||
STATE_OFF: config.get(CONF_PAYLOAD_OFF),
|
STATE_OFF: config.get(CONF_PAYLOAD_OFF),
|
||||||
@ -191,7 +186,6 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
|
|||||||
SPEED_MEDIUM: config.get(CONF_PAYLOAD_MEDIUM_SPEED),
|
SPEED_MEDIUM: config.get(CONF_PAYLOAD_MEDIUM_SPEED),
|
||||||
SPEED_HIGH: config.get(CONF_PAYLOAD_HIGH_SPEED),
|
SPEED_HIGH: config.get(CONF_PAYLOAD_HIGH_SPEED),
|
||||||
}
|
}
|
||||||
self._speed_list = config.get(CONF_SPEED_LIST)
|
|
||||||
optimistic = config.get(CONF_OPTIMISTIC)
|
optimistic = config.get(CONF_OPTIMISTIC)
|
||||||
self._optimistic = optimistic or self._topic[CONF_STATE_TOPIC] is None
|
self._optimistic = optimistic or self._topic[CONF_STATE_TOPIC] is None
|
||||||
self._optimistic_oscillation = (
|
self._optimistic_oscillation = (
|
||||||
@ -232,7 +226,7 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
|
|||||||
topics[CONF_STATE_TOPIC] = {
|
topics[CONF_STATE_TOPIC] = {
|
||||||
'topic': self._topic[CONF_STATE_TOPIC],
|
'topic': self._topic[CONF_STATE_TOPIC],
|
||||||
'msg_callback': state_received,
|
'msg_callback': state_received,
|
||||||
'qos': self._qos}
|
'qos': self._config.get(CONF_QOS)}
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def speed_received(topic, payload, qos):
|
def speed_received(topic, payload, qos):
|
||||||
@ -250,7 +244,7 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
|
|||||||
topics[CONF_SPEED_STATE_TOPIC] = {
|
topics[CONF_SPEED_STATE_TOPIC] = {
|
||||||
'topic': self._topic[CONF_SPEED_STATE_TOPIC],
|
'topic': self._topic[CONF_SPEED_STATE_TOPIC],
|
||||||
'msg_callback': speed_received,
|
'msg_callback': speed_received,
|
||||||
'qos': self._qos}
|
'qos': self._config.get(CONF_QOS)}
|
||||||
self._speed = SPEED_OFF
|
self._speed = SPEED_OFF
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
@ -267,7 +261,7 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
|
|||||||
topics[CONF_OSCILLATION_STATE_TOPIC] = {
|
topics[CONF_OSCILLATION_STATE_TOPIC] = {
|
||||||
'topic': self._topic[CONF_OSCILLATION_STATE_TOPIC],
|
'topic': self._topic[CONF_OSCILLATION_STATE_TOPIC],
|
||||||
'msg_callback': oscillation_received,
|
'msg_callback': oscillation_received,
|
||||||
'qos': self._qos}
|
'qos': self._config.get(CONF_QOS)}
|
||||||
self._oscillation = False
|
self._oscillation = False
|
||||||
|
|
||||||
self._sub_state = await subscription.async_subscribe_topics(
|
self._sub_state = await subscription.async_subscribe_topics(
|
||||||
@ -297,12 +291,12 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
|
|||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
"""Get entity name."""
|
"""Get entity name."""
|
||||||
return self._name
|
return self._config.get(CONF_NAME)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def speed_list(self) -> list:
|
def speed_list(self) -> list:
|
||||||
"""Get the list of available speeds."""
|
"""Get the list of available speeds."""
|
||||||
return self._speed_list
|
return self._config.get(CONF_SPEED_LIST)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supported_features(self) -> int:
|
def supported_features(self) -> int:
|
||||||
@ -326,7 +320,8 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
|
|||||||
"""
|
"""
|
||||||
mqtt.async_publish(
|
mqtt.async_publish(
|
||||||
self.hass, self._topic[CONF_COMMAND_TOPIC],
|
self.hass, self._topic[CONF_COMMAND_TOPIC],
|
||||||
self._payload[STATE_ON], self._qos, self._retain)
|
self._payload[STATE_ON], self._config.get(CONF_QOS),
|
||||||
|
self._config.get(CONF_RETAIN))
|
||||||
if speed:
|
if speed:
|
||||||
await self.async_set_speed(speed)
|
await self.async_set_speed(speed)
|
||||||
|
|
||||||
@ -337,7 +332,8 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
|
|||||||
"""
|
"""
|
||||||
mqtt.async_publish(
|
mqtt.async_publish(
|
||||||
self.hass, self._topic[CONF_COMMAND_TOPIC],
|
self.hass, self._topic[CONF_COMMAND_TOPIC],
|
||||||
self._payload[STATE_OFF], self._qos, self._retain)
|
self._payload[STATE_OFF], self._config.get(CONF_QOS),
|
||||||
|
self._config.get(CONF_RETAIN))
|
||||||
|
|
||||||
async def async_set_speed(self, speed: str) -> None:
|
async def async_set_speed(self, speed: str) -> None:
|
||||||
"""Set the speed of the fan.
|
"""Set the speed of the fan.
|
||||||
@ -358,7 +354,8 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
|
|||||||
|
|
||||||
mqtt.async_publish(
|
mqtt.async_publish(
|
||||||
self.hass, self._topic[CONF_SPEED_COMMAND_TOPIC],
|
self.hass, self._topic[CONF_SPEED_COMMAND_TOPIC],
|
||||||
mqtt_payload, self._qos, self._retain)
|
mqtt_payload, self._config.get(CONF_QOS),
|
||||||
|
self._config.get(CONF_RETAIN))
|
||||||
|
|
||||||
if self._optimistic_speed:
|
if self._optimistic_speed:
|
||||||
self._speed = speed
|
self._speed = speed
|
||||||
@ -379,7 +376,7 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
|
|||||||
|
|
||||||
mqtt.async_publish(
|
mqtt.async_publish(
|
||||||
self.hass, self._topic[CONF_OSCILLATION_COMMAND_TOPIC],
|
self.hass, self._topic[CONF_OSCILLATION_COMMAND_TOPIC],
|
||||||
payload, self._qos, self._retain)
|
payload, self._config.get(CONF_QOS), self._config.get(CONF_RETAIN))
|
||||||
|
|
||||||
if self._optimistic_oscillation:
|
if self._optimistic_oscillation:
|
||||||
self._oscillation = oscillating
|
self._oscillation = oscillating
|
||||||
|
@ -20,7 +20,7 @@ from homeassistant.core import split_entity_id
|
|||||||
from homeassistant.helpers import template
|
from homeassistant.helpers import template
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
REQUIREMENTS = ['numpy==1.15.4', 'pillow==5.2.0', 'protobuf==3.6.1']
|
REQUIREMENTS = ['numpy==1.15.4', 'pillow==5.3.0', 'protobuf==3.6.1']
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ from homeassistant.components.notify import (
|
|||||||
BaseNotificationService)
|
BaseNotificationService)
|
||||||
from homeassistant.const import (CONF_API_KEY, CONF_USERNAME, CONF_ICON)
|
from homeassistant.const import (CONF_API_KEY, CONF_USERNAME, CONF_ICON)
|
||||||
|
|
||||||
REQUIREMENTS = ['slacker==0.9.65']
|
REQUIREMENTS = ['slacker==0.11.0']
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -39,14 +39,15 @@ ATTR_FILE_AUTH_DIGEST = 'digest'
|
|||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
vol.Required(CONF_API_KEY): cv.string,
|
vol.Required(CONF_API_KEY): cv.string,
|
||||||
vol.Required(CONF_CHANNEL): cv.string,
|
vol.Required(CONF_CHANNEL): cv.string,
|
||||||
vol.Optional(CONF_USERNAME): cv.string,
|
|
||||||
vol.Optional(CONF_ICON): cv.string,
|
vol.Optional(CONF_ICON): cv.string,
|
||||||
|
vol.Optional(CONF_USERNAME): cv.string,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
def get_service(hass, config, discovery_info=None):
|
def get_service(hass, config, discovery_info=None):
|
||||||
"""Get the Slack notification service."""
|
"""Get the Slack notification service."""
|
||||||
import slacker
|
import slacker
|
||||||
|
|
||||||
channel = config.get(CONF_CHANNEL)
|
channel = config.get(CONF_CHANNEL)
|
||||||
api_key = config.get(CONF_API_KEY)
|
api_key = config.get(CONF_API_KEY)
|
||||||
username = config.get(CONF_USERNAME)
|
username = config.get(CONF_USERNAME)
|
||||||
@ -115,15 +116,15 @@ class SlackNotificationService(BaseNotificationService):
|
|||||||
'content': None,
|
'content': None,
|
||||||
'filetype': None,
|
'filetype': None,
|
||||||
'filename': filename,
|
'filename': filename,
|
||||||
# if optional title is none use the filename
|
# If optional title is none use the filename
|
||||||
'title': title if title else filename,
|
'title': title if title else filename,
|
||||||
'initial_comment': message,
|
'initial_comment': message,
|
||||||
'channels': target
|
'channels': target
|
||||||
}
|
}
|
||||||
# Post to slack
|
# Post to slack
|
||||||
self.slack.files.post('files.upload',
|
self.slack.files.post(
|
||||||
data=data,
|
'files.upload', data=data,
|
||||||
files={'file': file_as_bytes})
|
files={'file': file_as_bytes})
|
||||||
else:
|
else:
|
||||||
self.slack.chat.post_message(
|
self.slack.chat.post_message(
|
||||||
target, message, as_user=self._as_user,
|
target, message, as_user=self._as_user,
|
||||||
@ -154,13 +155,13 @@ class SlackNotificationService(BaseNotificationService):
|
|||||||
elif local_path:
|
elif local_path:
|
||||||
# Check whether path is whitelisted in configuration.yaml
|
# Check whether path is whitelisted in configuration.yaml
|
||||||
if self.is_allowed_path(local_path):
|
if self.is_allowed_path(local_path):
|
||||||
return open(local_path, "rb")
|
return open(local_path, 'rb')
|
||||||
_LOGGER.warning("'%s' is not secure to load data from!",
|
_LOGGER.warning(
|
||||||
local_path)
|
"'%s' is not secure to load data from!", local_path)
|
||||||
else:
|
else:
|
||||||
_LOGGER.warning("Neither URL nor local path found in params!")
|
_LOGGER.warning("Neither URL nor local path found in params!")
|
||||||
|
|
||||||
except OSError as error:
|
except OSError as error:
|
||||||
_LOGGER.error("Can't load from url or local path: %s", error)
|
_LOGGER.error("Can't load from URL or local path: %s", error)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
@ -18,7 +18,7 @@ from homeassistant.loader import bind_hass
|
|||||||
from homeassistant.util import sanitize_filename
|
from homeassistant.util import sanitize_filename
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
REQUIREMENTS = ['restrictedpython==4.0b6']
|
REQUIREMENTS = ['restrictedpython==4.0b7']
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -48,8 +48,8 @@ PLATFORM_SCHEMA = mqtt.MQTT_RO_PLATFORM_SCHEMA.extend({
|
|||||||
vol.Optional(CONF_JSON_ATTRS, default=[]): cv.ensure_list_csv,
|
vol.Optional(CONF_JSON_ATTRS, default=[]): cv.ensure_list_csv,
|
||||||
vol.Optional(CONF_EXPIRE_AFTER): cv.positive_int,
|
vol.Optional(CONF_EXPIRE_AFTER): cv.positive_int,
|
||||||
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean,
|
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean,
|
||||||
# Integrations shouldn't never expose unique_id through configuration
|
# Integrations should never expose unique_id through configuration.
|
||||||
# this here is an exception because MQTT is a msg transport, not a protocol
|
# This is an exception because MQTT is a message transport, not a protocol.
|
||||||
vol.Optional(CONF_UNIQUE_ID): cv.string,
|
vol.Optional(CONF_UNIQUE_ID): cv.string,
|
||||||
vol.Optional(CONF_DEVICE): mqtt.MQTT_ENTITY_DEVICE_INFO_SCHEMA,
|
vol.Optional(CONF_DEVICE): mqtt.MQTT_ENTITY_DEVICE_INFO_SCHEMA,
|
||||||
}).extend(mqtt.MQTT_AVAILABILITY_SCHEMA.schema)
|
}).extend(mqtt.MQTT_AVAILABILITY_SCHEMA.schema)
|
||||||
@ -86,32 +86,20 @@ class MqttSensor(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
|
|||||||
|
|
||||||
def __init__(self, config, discovery_hash):
|
def __init__(self, config, discovery_hash):
|
||||||
"""Initialize the sensor."""
|
"""Initialize the sensor."""
|
||||||
|
self._config = config
|
||||||
|
self._unique_id = config.get(CONF_UNIQUE_ID)
|
||||||
self._state = STATE_UNKNOWN
|
self._state = STATE_UNKNOWN
|
||||||
self._sub_state = None
|
self._sub_state = None
|
||||||
self._expiration_trigger = None
|
self._expiration_trigger = None
|
||||||
self._attributes = None
|
self._attributes = None
|
||||||
|
|
||||||
self._name = None
|
|
||||||
self._state_topic = None
|
|
||||||
self._qos = None
|
|
||||||
self._unit_of_measurement = None
|
|
||||||
self._force_update = None
|
|
||||||
self._template = None
|
|
||||||
self._expire_after = None
|
|
||||||
self._icon = None
|
|
||||||
self._device_class = None
|
|
||||||
self._json_attributes = None
|
|
||||||
self._unique_id = None
|
|
||||||
|
|
||||||
# Load config
|
|
||||||
self._setup_from_config(config)
|
|
||||||
|
|
||||||
availability_topic = config.get(CONF_AVAILABILITY_TOPIC)
|
availability_topic = config.get(CONF_AVAILABILITY_TOPIC)
|
||||||
payload_available = config.get(CONF_PAYLOAD_AVAILABLE)
|
payload_available = config.get(CONF_PAYLOAD_AVAILABLE)
|
||||||
payload_not_available = config.get(CONF_PAYLOAD_NOT_AVAILABLE)
|
payload_not_available = config.get(CONF_PAYLOAD_NOT_AVAILABLE)
|
||||||
|
qos = config.get(CONF_QOS)
|
||||||
device_config = config.get(CONF_DEVICE)
|
device_config = config.get(CONF_DEVICE)
|
||||||
|
|
||||||
MqttAvailability.__init__(self, availability_topic, self._qos,
|
MqttAvailability.__init__(self, availability_topic, qos,
|
||||||
payload_available, payload_not_available)
|
payload_available, payload_not_available)
|
||||||
MqttDiscoveryUpdate.__init__(self, discovery_hash,
|
MqttDiscoveryUpdate.__init__(self, discovery_hash,
|
||||||
self.discovery_update)
|
self.discovery_update)
|
||||||
@ -125,35 +113,23 @@ class MqttSensor(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
|
|||||||
async def discovery_update(self, discovery_payload):
|
async def discovery_update(self, discovery_payload):
|
||||||
"""Handle updated discovery message."""
|
"""Handle updated discovery message."""
|
||||||
config = PLATFORM_SCHEMA(discovery_payload)
|
config = PLATFORM_SCHEMA(discovery_payload)
|
||||||
self._setup_from_config(config)
|
self._config = config
|
||||||
await self.availability_discovery_update(config)
|
await self.availability_discovery_update(config)
|
||||||
await self._subscribe_topics()
|
await self._subscribe_topics()
|
||||||
self.async_schedule_update_ha_state()
|
self.async_schedule_update_ha_state()
|
||||||
|
|
||||||
def _setup_from_config(self, config):
|
|
||||||
"""(Re)Setup the entity."""
|
|
||||||
self._name = config.get(CONF_NAME)
|
|
||||||
self._state_topic = config.get(CONF_STATE_TOPIC)
|
|
||||||
self._qos = config.get(CONF_QOS)
|
|
||||||
self._unit_of_measurement = config.get(CONF_UNIT_OF_MEASUREMENT)
|
|
||||||
self._force_update = config.get(CONF_FORCE_UPDATE)
|
|
||||||
self._expire_after = config.get(CONF_EXPIRE_AFTER)
|
|
||||||
self._icon = config.get(CONF_ICON)
|
|
||||||
self._device_class = config.get(CONF_DEVICE_CLASS)
|
|
||||||
self._template = config.get(CONF_VALUE_TEMPLATE)
|
|
||||||
self._json_attributes = set(config.get(CONF_JSON_ATTRS))
|
|
||||||
self._unique_id = config.get(CONF_UNIQUE_ID)
|
|
||||||
|
|
||||||
async def _subscribe_topics(self):
|
async def _subscribe_topics(self):
|
||||||
"""(Re)Subscribe to topics."""
|
"""(Re)Subscribe to topics."""
|
||||||
if self._template is not None:
|
template = self._config.get(CONF_VALUE_TEMPLATE)
|
||||||
self._template.hass = self.hass
|
if template is not None:
|
||||||
|
template.hass = self.hass
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def message_received(topic, payload, qos):
|
def message_received(topic, payload, qos):
|
||||||
"""Handle new MQTT messages."""
|
"""Handle new MQTT messages."""
|
||||||
# auto-expire enabled?
|
# auto-expire enabled?
|
||||||
if self._expire_after is not None and self._expire_after > 0:
|
expire_after = self._config.get(CONF_EXPIRE_AFTER)
|
||||||
|
if expire_after is not None and expire_after > 0:
|
||||||
# Reset old trigger
|
# Reset old trigger
|
||||||
if self._expiration_trigger:
|
if self._expiration_trigger:
|
||||||
self._expiration_trigger()
|
self._expiration_trigger()
|
||||||
@ -161,18 +137,19 @@ class MqttSensor(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
|
|||||||
|
|
||||||
# Set new trigger
|
# Set new trigger
|
||||||
expiration_at = (
|
expiration_at = (
|
||||||
dt_util.utcnow() + timedelta(seconds=self._expire_after))
|
dt_util.utcnow() + timedelta(seconds=expire_after))
|
||||||
|
|
||||||
self._expiration_trigger = async_track_point_in_utc_time(
|
self._expiration_trigger = async_track_point_in_utc_time(
|
||||||
self.hass, self.value_is_expired, expiration_at)
|
self.hass, self.value_is_expired, expiration_at)
|
||||||
|
|
||||||
if self._json_attributes:
|
json_attributes = set(self._config.get(CONF_JSON_ATTRS))
|
||||||
|
if json_attributes:
|
||||||
self._attributes = {}
|
self._attributes = {}
|
||||||
try:
|
try:
|
||||||
json_dict = json.loads(payload)
|
json_dict = json.loads(payload)
|
||||||
if isinstance(json_dict, dict):
|
if isinstance(json_dict, dict):
|
||||||
attrs = {k: json_dict[k] for k in
|
attrs = {k: json_dict[k] for k in
|
||||||
self._json_attributes & json_dict.keys()}
|
json_attributes & json_dict.keys()}
|
||||||
self._attributes = attrs
|
self._attributes = attrs
|
||||||
else:
|
else:
|
||||||
_LOGGER.warning("JSON result was not a dictionary")
|
_LOGGER.warning("JSON result was not a dictionary")
|
||||||
@ -180,17 +157,17 @@ class MqttSensor(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
|
|||||||
_LOGGER.warning("MQTT payload could not be parsed as JSON")
|
_LOGGER.warning("MQTT payload could not be parsed as JSON")
|
||||||
_LOGGER.debug("Erroneous JSON: %s", payload)
|
_LOGGER.debug("Erroneous JSON: %s", payload)
|
||||||
|
|
||||||
if self._template is not None:
|
if template is not None:
|
||||||
payload = self._template.async_render_with_possible_json_value(
|
payload = template.async_render_with_possible_json_value(
|
||||||
payload, self._state)
|
payload, self._state)
|
||||||
self._state = payload
|
self._state = payload
|
||||||
self.async_schedule_update_ha_state()
|
self.async_schedule_update_ha_state()
|
||||||
|
|
||||||
self._sub_state = await subscription.async_subscribe_topics(
|
self._sub_state = await subscription.async_subscribe_topics(
|
||||||
self.hass, self._sub_state,
|
self.hass, self._sub_state,
|
||||||
{'state_topic': {'topic': self._state_topic,
|
{'state_topic': {'topic': self._config.get(CONF_STATE_TOPIC),
|
||||||
'msg_callback': message_received,
|
'msg_callback': message_received,
|
||||||
'qos': self._qos}})
|
'qos': self._config.get(CONF_QOS)}})
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self):
|
async def async_will_remove_from_hass(self):
|
||||||
"""Unsubscribe when removed."""
|
"""Unsubscribe when removed."""
|
||||||
@ -212,17 +189,17 @@ class MqttSensor(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
|
|||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Return the name of the sensor."""
|
"""Return the name of the sensor."""
|
||||||
return self._name
|
return self._config.get(CONF_NAME)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unit_of_measurement(self):
|
def unit_of_measurement(self):
|
||||||
"""Return the unit this state is expressed in."""
|
"""Return the unit this state is expressed in."""
|
||||||
return self._unit_of_measurement
|
return self._config.get(CONF_UNIT_OF_MEASUREMENT)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def force_update(self):
|
def force_update(self):
|
||||||
"""Force update."""
|
"""Force update."""
|
||||||
return self._force_update
|
return self._config.get(CONF_FORCE_UPDATE)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self):
|
def state(self):
|
||||||
@ -242,9 +219,9 @@ class MqttSensor(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
|
|||||||
@property
|
@property
|
||||||
def icon(self):
|
def icon(self):
|
||||||
"""Return the icon."""
|
"""Return the icon."""
|
||||||
return self._icon
|
return self._config.get(CONF_ICON)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_class(self) -> Optional[str]:
|
def device_class(self) -> Optional[str]:
|
||||||
"""Return the device class of the sensor."""
|
"""Return the device class of the sensor."""
|
||||||
return self._device_class
|
return self._config.get(CONF_DEVICE_CLASS)
|
||||||
|
@ -19,7 +19,7 @@ import homeassistant.helpers.config_validation as cv
|
|||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.util import Throttle
|
from homeassistant.util import Throttle
|
||||||
|
|
||||||
REQUIREMENTS = ['pytautulli==0.4.0']
|
REQUIREMENTS = ['pytautulli==0.4.1']
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -90,9 +90,9 @@ class TautulliSensor(Entity):
|
|||||||
await self.tautulli.async_update()
|
await self.tautulli.async_update()
|
||||||
self.home = self.tautulli.api.home_data
|
self.home = self.tautulli.api.home_data
|
||||||
self.sessions = self.tautulli.api.session_data
|
self.sessions = self.tautulli.api.session_data
|
||||||
self._attributes['Top Movie'] = self.home[0]['rows'][0]['title']
|
self._attributes['Top Movie'] = self.home.get('movie')
|
||||||
self._attributes['Top TV Show'] = self.home[3]['rows'][0]['title']
|
self._attributes['Top TV Show'] = self.home.get('tv')
|
||||||
self._attributes['Top User'] = self.home[7]['rows'][0]['user']
|
self._attributes['Top User'] = self.home.get('user')
|
||||||
for key in self.sessions:
|
for key in self.sessions:
|
||||||
if 'sessions' not in key:
|
if 'sessions' not in key:
|
||||||
self._attributes[key] = self.sessions[key]
|
self._attributes[key] = self.sessions[key]
|
||||||
|
@ -15,7 +15,7 @@ from homeassistant.helpers import config_validation as cv
|
|||||||
|
|
||||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
||||||
|
|
||||||
REQUIREMENTS = ['pywemo==0.4.29']
|
REQUIREMENTS = ['pywemo==0.4.33']
|
||||||
|
|
||||||
DOMAIN = 'wemo'
|
DOMAIN = 'wemo'
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ pip>=8.0.3
|
|||||||
pytz>=2018.04
|
pytz>=2018.04
|
||||||
pyyaml>=3.13,<4
|
pyyaml>=3.13,<4
|
||||||
requests==2.20.1
|
requests==2.20.1
|
||||||
ruamel.yaml==0.15.78
|
ruamel.yaml==0.15.80
|
||||||
voluptuous==0.11.5
|
voluptuous==0.11.5
|
||||||
voluptuous-serialize==2.0.0
|
voluptuous-serialize==2.0.0
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import os
|
|||||||
|
|
||||||
from homeassistant.util.yaml import _SECRET_NAMESPACE
|
from homeassistant.util.yaml import _SECRET_NAMESPACE
|
||||||
|
|
||||||
REQUIREMENTS = ['keyring==15.1.0', 'keyrings.alt==3.1']
|
REQUIREMENTS = ['keyring==17.0.0', 'keyrings.alt==3.1']
|
||||||
|
|
||||||
|
|
||||||
def run(args):
|
def run(args):
|
||||||
|
@ -12,7 +12,7 @@ pip>=8.0.3
|
|||||||
pytz>=2018.04
|
pytz>=2018.04
|
||||||
pyyaml>=3.13,<4
|
pyyaml>=3.13,<4
|
||||||
requests==2.20.1
|
requests==2.20.1
|
||||||
ruamel.yaml==0.15.78
|
ruamel.yaml==0.15.80
|
||||||
voluptuous==0.11.5
|
voluptuous==0.11.5
|
||||||
voluptuous-serialize==2.0.0
|
voluptuous-serialize==2.0.0
|
||||||
|
|
||||||
@ -426,7 +426,7 @@ geojson_client==0.3
|
|||||||
georss_client==0.4
|
georss_client==0.4
|
||||||
|
|
||||||
# homeassistant.components.device_tracker.googlehome
|
# homeassistant.components.device_tracker.googlehome
|
||||||
ghlocalapi==0.1.0
|
ghlocalapi==0.3.5
|
||||||
|
|
||||||
# homeassistant.components.sensor.gitter
|
# homeassistant.components.sensor.gitter
|
||||||
gitterpy==0.1.7
|
gitterpy==0.1.7
|
||||||
@ -548,7 +548,7 @@ jsonrpc-async==0.6
|
|||||||
jsonrpc-websocket==0.6
|
jsonrpc-websocket==0.6
|
||||||
|
|
||||||
# homeassistant.scripts.keyring
|
# homeassistant.scripts.keyring
|
||||||
keyring==15.1.0
|
keyring==17.0.0
|
||||||
|
|
||||||
# homeassistant.scripts.keyring
|
# homeassistant.scripts.keyring
|
||||||
keyrings.alt==3.1
|
keyrings.alt==3.1
|
||||||
@ -748,7 +748,7 @@ pilight==0.1.1
|
|||||||
|
|
||||||
# homeassistant.components.camera.proxy
|
# homeassistant.components.camera.proxy
|
||||||
# homeassistant.components.image_processing.tensorflow
|
# homeassistant.components.image_processing.tensorflow
|
||||||
pillow==5.2.0
|
pillow==5.3.0
|
||||||
|
|
||||||
# homeassistant.components.dominos
|
# homeassistant.components.dominos
|
||||||
pizzapi==0.0.3
|
pizzapi==0.0.3
|
||||||
@ -1158,7 +1158,7 @@ pystride==0.1.7
|
|||||||
pysyncthru==0.3.1
|
pysyncthru==0.3.1
|
||||||
|
|
||||||
# homeassistant.components.sensor.tautulli
|
# homeassistant.components.sensor.tautulli
|
||||||
pytautulli==0.4.0
|
pytautulli==0.4.1
|
||||||
|
|
||||||
# homeassistant.components.media_player.liveboxplaytv
|
# homeassistant.components.media_player.liveboxplaytv
|
||||||
pyteleloisirs==3.4
|
pyteleloisirs==3.4
|
||||||
@ -1327,7 +1327,7 @@ pyvlx==0.1.3
|
|||||||
pywebpush==1.6.0
|
pywebpush==1.6.0
|
||||||
|
|
||||||
# homeassistant.components.wemo
|
# homeassistant.components.wemo
|
||||||
pywemo==0.4.29
|
pywemo==0.4.33
|
||||||
|
|
||||||
# homeassistant.components.camera.xeoma
|
# homeassistant.components.camera.xeoma
|
||||||
pyxeoma==1.4.0
|
pyxeoma==1.4.0
|
||||||
@ -1357,7 +1357,7 @@ raincloudy==0.0.5
|
|||||||
regenmaschine==1.0.7
|
regenmaschine==1.0.7
|
||||||
|
|
||||||
# homeassistant.components.python_script
|
# homeassistant.components.python_script
|
||||||
restrictedpython==4.0b6
|
restrictedpython==4.0b7
|
||||||
|
|
||||||
# homeassistant.components.rflink
|
# homeassistant.components.rflink
|
||||||
rflink==0.0.37
|
rflink==0.0.37
|
||||||
@ -1427,7 +1427,7 @@ sisyphus-control==2.1
|
|||||||
skybellpy==0.1.2
|
skybellpy==0.1.2
|
||||||
|
|
||||||
# homeassistant.components.notify.slack
|
# homeassistant.components.notify.slack
|
||||||
slacker==0.9.65
|
slacker==0.11.0
|
||||||
|
|
||||||
# homeassistant.components.sleepiq
|
# homeassistant.components.sleepiq
|
||||||
sleepyq==0.6
|
sleepyq==0.6
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
Sphinx==1.8.2
|
Sphinx==1.8.2
|
||||||
sphinx-autodoc-typehints==1.5.0
|
sphinx-autodoc-typehints==1.5.1
|
||||||
sphinx-autodoc-annotation==1.0.post1
|
sphinx-autodoc-annotation==1.0.post1
|
||||||
|
@ -221,7 +221,7 @@ pywebpush==1.6.0
|
|||||||
regenmaschine==1.0.7
|
regenmaschine==1.0.7
|
||||||
|
|
||||||
# homeassistant.components.python_script
|
# homeassistant.components.python_script
|
||||||
restrictedpython==4.0b6
|
restrictedpython==4.0b7
|
||||||
|
|
||||||
# homeassistant.components.rflink
|
# homeassistant.components.rflink
|
||||||
rflink==0.0.37
|
rflink==0.0.37
|
||||||
|
2
setup.py
2
setup.py
@ -46,7 +46,7 @@ REQUIRES = [
|
|||||||
'pytz>=2018.04',
|
'pytz>=2018.04',
|
||||||
'pyyaml>=3.13,<4',
|
'pyyaml>=3.13,<4',
|
||||||
'requests==2.20.1',
|
'requests==2.20.1',
|
||||||
'ruamel.yaml==0.15.78',
|
'ruamel.yaml==0.15.80',
|
||||||
'voluptuous==0.11.5',
|
'voluptuous==0.11.5',
|
||||||
'voluptuous-serialize==2.0.0',
|
'voluptuous-serialize==2.0.0',
|
||||||
]
|
]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user