Compare commits

..

35 Commits

Author SHA1 Message Date
Franck Nijhof
7c783dc1b4 Merge pull request #43102 from home-assistant/rc
Co-authored-by: Sören Oldag <soeren_oldag@freenet.de>
Co-authored-by: Hmmbob <33529490+hmmbob@users.noreply.github.com>
Co-authored-by: jjlawren <jjlawren@users.noreply.github.com>
2020-11-11 18:30:59 +01:00
Franck Nijhof
650f3413a4 Bumped version to 0.117.6 2020-11-11 18:04:17 +01:00
jjlawren
176c2f3978 Fix Plex auth issues by setting header (#43081) 2020-11-11 18:01:48 +01:00
Hmmbob
9d617d446e Bump gTTS-token to 1.1.4 (#43015) 2020-11-11 17:59:07 +01:00
Sören Oldag
ea5f621351 Bump pwmled to v1.6.7 (#42903) 2020-11-11 17:58:58 +01:00
Sören Oldag
b49aa9485c Remove unneeded state restoration of the physical device in rpi_gpio_pwm integration (#42804)
* Add @soldag to code owners of rpi_gpio_pwm platform

* Remove unneeded state restoration of the physical device in rpi_gpio_pwm integration
2020-11-11 17:58:48 +01:00
Paulus Schoutsen
22f16759e5 Merge pull request #42874 from home-assistant/rc 2020-11-05 16:33:21 +01:00
rikroe
8895c65dd4 Bump bimmer_connected to 0.7.12 (#42875)
Co-authored-by: rikroe <rikroe@users.noreply.github.com>
2020-11-05 15:32:12 +00:00
Paulus Schoutsen
dfed834617 Bumped version to 0.117.5 2020-11-05 13:45:58 +00:00
Andreas Billmeier
7d0f5fa31a Revert "Fix broken maxcube component" (#42859)
This reverts commit 898f50386f.
2020-11-05 13:45:43 +00:00
cgtobi
b65c92ce91 Fix Netatmo public weather sensor bug (#42858) 2020-11-05 13:45:42 +00:00
Aaron Bach
7c084975b7 Fix missing/incorrect SimpliSafe entities (#42846)
* Entity types

* Don't overdo it

* Fix missing/incorrect SimpliSafe entities
2020-11-05 13:44:57 +00:00
Aaron Bach
943cc243b5 Fix missing sensor exceptions in SimpliSafe (#42845)
* Fix missing sensor exceptions in SimpliSafe

* Entity types

* Don't overdo it
2020-11-05 13:44:56 +00:00
Aaron Bach
ba48fd6c51 Clean up SimpliSafe binary sensor implementation (#42841)
* Clean up SimpliSafe binary sensor implementation

* Cleanup

* Constant name
2020-11-05 13:44:55 +00:00
Erik Montnemery
2f1d30fa85 Bump hatasmota to 0.0.25.1 (#42850) 2020-11-04 21:59:08 +01:00
Paulus Schoutsen
7a96f8a4eb Merge pull request #42836 from home-assistant/rc 2020-11-04 17:20:54 +01:00
Paulus Schoutsen
df6ee2e51f Bumped version to 0.117.4 2020-11-04 15:47:28 +00:00
Maciej Bieniek
6bacda3cee Call coordinator.shutdown() when ConfigEntryNotReady (#42833) 2020-11-04 15:47:11 +00:00
Rob Bierbooms
d4b68454a3 Cleanup dispatchers when unloading rfxtrx (#42803)
* Cleanup dispatchers

* Fix name

* Refactor code

* Fix typo in function description

* Fix pylint error

* Change function definition

* Move cleanup_callbacks data to domain
2020-11-04 15:47:11 +00:00
Clifford Roche
36b099592e Update greeclimate to 0.9.5 (#42796)
Provides better discovery across subnets in some cases
2020-11-04 15:47:09 +00:00
Paulus Schoutsen
d156e95f8a Merge pull request #42824 from home-assistant/rc 2020-11-04 12:22:18 +01:00
Paulus Schoutsen
f3c7b77afa Bumped version to 0.117.3 2020-11-04 09:24:41 +00:00
Paulus Schoutsen
45dbd49852 Fix evohome scheduling coroutines (#42821) 2020-11-04 09:24:33 +00:00
J. Nick Koston
e4f88a02f7 Fix rest sensors with resource templates (#42818) 2020-11-04 09:24:32 +00:00
Rob Bierbooms
32652fde48 Filter rfxtrx replace devices in option flow on existing config entry (#42800)
* Fix function _can_replace_device

* Rearrange
2020-11-04 09:24:31 +00:00
rikroe
0dc926a131 Bump bimmer_connected to 0.7.11 (#42788) 2020-11-04 09:24:30 +00:00
Michael
43486917bf Fix broken 2fa authentication in synology_dsm (#42775) 2020-11-04 09:24:30 +00:00
cgtobi
d967ecc8c6 Bump pyatmo to 4.2.0 (#42774) 2020-11-04 09:24:29 +00:00
Erik Montnemery
a7bdd2aafe Force color or white mode exclusivity for Tasmota lights (#42772) 2020-11-04 09:24:28 +00:00
Aaron Bach
e6cc35cff2 Fix incorrect property usage for SimpliSafe (#42770) 2020-11-04 09:24:27 +00:00
Aaron Bach
b7d0a21a8b Bump pyairvisual to 5.0.4 (#42760) 2020-11-04 09:24:26 +00:00
rikroe
beaaa1478c Bump bimmer_connected to 0.7.10: fix login issues, add (PH)EV services (#42747)
Co-authored-by: rikroe <rikroe@users.noreply.github.com>
2020-11-04 09:24:25 +00:00
Raman Gupta
74d8569aab Fix Vizio host string for zeroconf discovery (#42738) 2020-11-04 09:24:25 +00:00
Andreas Billmeier
dc0d27ec18 Fix broken maxcube component (#42674) 2020-11-04 09:24:24 +00:00
Andreas Billmeier
64707d89dd Please set exact cryptography version cryptography==3.2 (#42611) 2020-11-04 09:24:23 +00:00
44 changed files with 287 additions and 160 deletions

View File

@@ -362,6 +362,7 @@ homeassistant/components/rmvtransport/* @cgtobi
homeassistant/components/roku/* @ctalkington
homeassistant/components/roomba/* @pschmitt @cyr-ius @shenxn
homeassistant/components/roon/* @pavoni
homeassistant/components/rpi_gpio_pwm/* @soldag
homeassistant/components/rpi_power/* @shenxn @swetoast
homeassistant/components/ruckus_unleashed/* @gabe565
homeassistant/components/safe_mode/* @home-assistant/core

View File

@@ -3,6 +3,6 @@
"name": "AirVisual",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/airvisual",
"requirements": ["pyairvisual==5.0.3"],
"requirements": ["pyairvisual==5.0.4"],
"codeowners": ["@bachya"]
}

View File

@@ -2,7 +2,7 @@
"domain": "bmw_connected_drive",
"name": "BMW Connected Drive",
"documentation": "https://www.home-assistant.io/integrations/bmw_connected_drive",
"requirements": ["bimmer_connected==0.7.8"],
"requirements": ["bimmer_connected==0.7.12"],
"dependencies": [],
"codeowners": ["@gerard33", "@rikroe"]
}

View File

@@ -34,6 +34,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
await coordinator.async_refresh()
if not coordinator.last_update_success:
coordinator.shutdown()
raise ConfigEntryNotReady
hass.data.setdefault(DOMAIN, {})

View File

@@ -431,7 +431,7 @@ class EvoBroker:
return
if refresh:
self.hass.helpers.event.async_call_later(1, self.async_update())
self.hass.helpers.event.async_call_later(1, self.async_update)
return result

View File

@@ -2,6 +2,6 @@
"domain": "google_translate",
"name": "Google Translate Text-to-Speech",
"documentation": "https://www.home-assistant.io/integrations/google_translate",
"requirements": ["gTTS-token==1.1.3"],
"requirements": ["gTTS-token==1.1.4"],
"codeowners": []
}

View File

@@ -3,6 +3,6 @@
"name": "Gree Climate",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/gree",
"requirements": ["greeclimate==0.9.2"],
"requirements": ["greeclimate==0.9.5"],
"codeowners": ["@cmroche"]
}
}

View File

@@ -3,7 +3,7 @@
"name": "Netatmo",
"documentation": "https://www.home-assistant.io/integrations/netatmo",
"requirements": [
"pyatmo==4.1.0"
"pyatmo==4.2.0"
],
"after_dependencies": [
"cloud",

View File

@@ -45,10 +45,10 @@ class NetatmoBase(Entity):
data_class["name"],
signal_name,
self.async_update_callback,
LAT_NE=data_class["LAT_NE"],
LON_NE=data_class["LON_NE"],
LAT_SW=data_class["LAT_SW"],
LON_SW=data_class["LON_SW"],
lat_ne=data_class["lat_ne"],
lon_ne=data_class["lon_ne"],
lat_sw=data_class["lat_sw"],
lon_sw=data_class["lon_sw"],
)
else:

View File

@@ -202,10 +202,10 @@ async def async_setup_entry(hass, entry, async_add_entities):
PUBLICDATA_DATA_CLASS_NAME,
signal_name,
None,
LAT_NE=area.lat_ne,
LON_NE=area.lon_ne,
LAT_SW=area.lat_sw,
LON_SW=area.lon_sw,
lat_ne=area.lat_ne,
lon_ne=area.lon_ne,
lat_sw=area.lat_sw,
lon_sw=area.lon_sw,
)
for sensor_type in SUPPORTED_PUBLIC_SENSOR_TYPES:
new_entities.append(
@@ -473,10 +473,10 @@ class NetatmoPublicSensor(NetatmoBase):
self._data_classes.append(
{
"name": PUBLICDATA_DATA_CLASS_NAME,
"LAT_NE": area.lat_ne,
"LON_NE": area.lon_ne,
"LAT_SW": area.lat_sw,
"LON_SW": area.lon_sw,
"lat_ne": area.lat_ne,
"lon_ne": area.lon_ne,
"lat_sw": area.lat_sw,
"lon_sw": area.lon_sw,
"area_name": area.area_name,
SIGNAL_NAME: self._signal_name,
}
@@ -563,10 +563,10 @@ class NetatmoPublicSensor(NetatmoBase):
self._data_classes = [
{
"name": PUBLICDATA_DATA_CLASS_NAME,
"LAT_NE": area.lat_ne,
"LON_NE": area.lon_ne,
"LAT_SW": area.lat_sw,
"LON_SW": area.lon_sw,
"lat_ne": area.lat_ne,
"lon_ne": area.lon_ne,
"lat_sw": area.lat_sw,
"lon_sw": area.lon_sw,
"area_name": area.area_name,
SIGNAL_NAME: self._signal_name,
}
@@ -577,10 +577,10 @@ class NetatmoPublicSensor(NetatmoBase):
PUBLICDATA_DATA_CLASS_NAME,
self._signal_name,
self.async_update_callback,
LAT_NE=area.lat_ne,
LON_NE=area.lon_ne,
LAT_SW=area.lat_sw,
LON_SW=area.lon_sw,
lat_ne=area.lat_ne,
lon_ne=area.lon_ne,
lat_sw=area.lat_sw,
lon_sw=area.lon_sw,
)
@callback

View File

@@ -289,6 +289,8 @@ class PlexFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
async def async_step_plex_website_auth(self):
"""Begin external auth flow on Plex website."""
self.hass.http.register_view(PlexAuthorizationCallbackView)
hass_url = get_url(self.hass)
headers = {"Origin": hass_url}
payload = {
"X-Plex-Device-Name": X_PLEX_DEVICE_NAME,
"X-Plex-Version": X_PLEX_VERSION,
@@ -298,9 +300,9 @@ class PlexFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
"X-Plex-Model": "Plex OAuth",
}
session = async_get_clientsession(self.hass)
self.plexauth = PlexAuth(payload, session)
self.plexauth = PlexAuth(payload, session, headers)
await self.plexauth.initiate_auth()
forward_url = f"{get_url(self.hass)}{AUTH_CALLBACK_PATH}?flow_id={self.flow_id}"
forward_url = f"{hass_url}{AUTH_CALLBACK_PATH}?flow_id={self.flow_id}"
auth_url = self.plexauth.auth_url(forward_url)
return self.async_external_step(step_id="obtain_token", url=auth_url)

View File

@@ -4,9 +4,9 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/plex",
"requirements": [
"plexapi==4.1.1",
"plexauth==0.0.5",
"plexwebsocket==0.0.12"
"plexapi==4.1.1",
"plexauth==0.0.6",
"plexwebsocket==0.0.12"
],
"dependencies": ["http"],
"after_dependencies": ["sonos"],

View File

@@ -84,7 +84,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
if resource_template is not None:
resource_template.hass = hass
resource = resource_template.render(parse_result=False)
resource = resource_template.async_render(parse_result=False)
if value_template is not None:
value_template.hass = hass
@@ -189,6 +189,6 @@ class RestBinarySensor(BinarySensorEntity):
async def async_update(self):
"""Get the latest data from REST API and updates the state."""
if self._resource_template is not None:
self.rest.set_url(self._resource_template.render(parse_result=False))
self.rest.set_url(self._resource_template.async_render(parse_result=False))
await self.rest.async_update()

View File

@@ -103,7 +103,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
if resource_template is not None:
resource_template.hass = hass
resource = resource_template.render(parse_result=False)
resource = resource_template.async_render(parse_result=False)
if username and password:
if config.get(CONF_AUTHENTICATION) == HTTP_DIGEST_AUTHENTICATION:
@@ -202,7 +202,7 @@ class RestSensor(Entity):
async def async_update(self):
"""Get the latest data from REST API and update the state."""
if self._resource_template is not None:
self.rest.set_url(self._resource_template.render(parse_result=False))
self.rest.set_url(self._resource_template.async_render(parse_result=False))
await self.rest.async_update()

View File

@@ -49,6 +49,9 @@ from .const import (
CONF_OFF_DELAY,
CONF_REMOVE_DEVICE,
CONF_SIGNAL_REPETITIONS,
DATA_CLEANUP_CALLBACKS,
DATA_LISTENER,
DATA_RFXOBJECT,
DEVICE_PACKET_TYPE_LIGHTING4,
EVENT_RFXTRX_EVENT,
SERVICE_SEND,
@@ -93,8 +96,6 @@ DATA_TYPES = OrderedDict(
)
_LOGGER = logging.getLogger(__name__)
DATA_RFXOBJECT = "rfxobject"
DATA_LISTENER = "ha_stop"
def _bytearray_string(data):
@@ -188,6 +189,8 @@ async def async_setup_entry(hass, entry: config_entries.ConfigEntry):
"""Set up the RFXtrx component."""
hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN][DATA_CLEANUP_CALLBACKS] = []
await async_setup_internal(hass, entry)
for domain in DOMAINS:
@@ -212,12 +215,17 @@ async def async_unload_entry(hass, entry: config_entries.ConfigEntry):
hass.services.async_remove(DOMAIN, SERVICE_SEND)
for cleanup_callback in hass.data[DOMAIN][DATA_CLEANUP_CALLBACKS]:
cleanup_callback()
listener = hass.data[DOMAIN][DATA_LISTENER]
listener()
rfx_object = hass.data[DOMAIN][DATA_RFXOBJECT]
await hass.async_add_executor_job(rfx_object.close_connection)
hass.data.pop(DOMAIN)
return True
@@ -428,6 +436,14 @@ def get_device_id(device, data_bits=None):
return (f"{device.packettype:x}", f"{device.subtype:x}", id_string)
def connect_auto_add(hass, entry_data, callback_fun):
"""Connect to dispatcher for automatic add."""
if entry_data[CONF_AUTOMATIC_ADD]:
hass.data[DOMAIN][DATA_CLEANUP_CALLBACKS].append(
hass.helpers.dispatcher.async_dispatcher_connect(SIGNAL_EVENT, callback_fun)
)
class RfxtrxEntity(RestoreEntity):
"""Represents a Rfxtrx device.

View File

@@ -19,11 +19,10 @@ from homeassistant.core import callback
from homeassistant.helpers import event as evt
from . import (
CONF_AUTOMATIC_ADD,
CONF_DATA_BITS,
CONF_OFF_DELAY,
SIGNAL_EVENT,
RfxtrxEntity,
connect_auto_add,
find_possible_pt2262_device,
get_device_id,
get_pt2262_cmd,
@@ -147,10 +146,7 @@ async def async_setup_entry(
async_add_entities([sensor])
# Subscribe to main RFXtrx events
if discovery_info[CONF_AUTOMATIC_ADD]:
hass.helpers.dispatcher.async_dispatcher_connect(
SIGNAL_EVENT, binary_sensor_update
)
connect_auto_add(hass, discovery_info, binary_sensor_update)
class RfxtrxBinarySensor(RfxtrxEntity, BinarySensorEntity):

View File

@@ -360,13 +360,17 @@ class OptionsFlow(config_entries.OptionsFlow):
"""Check if device can be replaced with selected device."""
device_data = self._get_device_data(entry_id)
event_code = device_data[CONF_EVENT_CODE]
rfx_obj = get_rfx_object(event_code)
if (
rfx_obj.device.packettype == self._selected_device_object.device.packettype
and rfx_obj.device.subtype == self._selected_device_object.device.subtype
and self._selected_device_event_code != event_code
):
return True
if event_code is not None:
rfx_obj = get_rfx_object(event_code)
if (
rfx_obj.device.packettype
== self._selected_device_object.device.packettype
and rfx_obj.device.subtype
== self._selected_device_object.device.subtype
and self._selected_device_event_code != event_code
):
return True
return False

View File

@@ -33,3 +33,7 @@ SERVICE_SEND = "send"
DEVICE_PACKET_TYPE_LIGHTING4 = 0x13
EVENT_RFXTRX_EVENT = "rfxtrx_event"
DATA_RFXOBJECT = "rfxobject"
DATA_LISTENER = "ha_stop"
DATA_CLEANUP_CALLBACKS = "cleanup_callbacks"

View File

@@ -6,12 +6,11 @@ from homeassistant.const import CONF_DEVICES, STATE_OPEN
from homeassistant.core import callback
from . import (
CONF_AUTOMATIC_ADD,
CONF_DATA_BITS,
CONF_SIGNAL_REPETITIONS,
DEFAULT_SIGNAL_REPETITIONS,
SIGNAL_EVENT,
RfxtrxCommandEntity,
connect_auto_add,
get_device_id,
get_rfx_object,
)
@@ -81,8 +80,7 @@ async def async_setup_entry(
async_add_entities([entity])
# Subscribe to main RFXtrx events
if discovery_info[CONF_AUTOMATIC_ADD]:
hass.helpers.dispatcher.async_dispatcher_connect(SIGNAL_EVENT, cover_update)
connect_auto_add(hass, discovery_info, cover_update)
class RfxtrxCover(RfxtrxCommandEntity, CoverEntity):

View File

@@ -12,12 +12,11 @@ from homeassistant.const import CONF_DEVICES, STATE_ON
from homeassistant.core import callback
from . import (
CONF_AUTOMATIC_ADD,
CONF_DATA_BITS,
CONF_SIGNAL_REPETITIONS,
DEFAULT_SIGNAL_REPETITIONS,
SIGNAL_EVENT,
RfxtrxCommandEntity,
connect_auto_add,
get_device_id,
get_rfx_object,
)
@@ -95,8 +94,7 @@ async def async_setup_entry(
async_add_entities([entity])
# Subscribe to main RFXtrx events
if discovery_info[CONF_AUTOMATIC_ADD]:
hass.helpers.dispatcher.async_dispatcher_connect(SIGNAL_EVENT, light_update)
connect_auto_add(hass, discovery_info, light_update)
class RfxtrxLight(RfxtrxCommandEntity, LightEntity):

View File

@@ -20,11 +20,10 @@ from homeassistant.const import (
from homeassistant.core import callback
from . import (
CONF_AUTOMATIC_ADD,
CONF_DATA_BITS,
DATA_TYPES,
SIGNAL_EVENT,
RfxtrxEntity,
connect_auto_add,
get_device_id,
get_rfx_object,
)
@@ -127,8 +126,7 @@ async def async_setup_entry(
async_add_entities([entity])
# Subscribe to main RFXtrx events
if discovery_info[CONF_AUTOMATIC_ADD]:
hass.helpers.dispatcher.async_dispatcher_connect(SIGNAL_EVENT, sensor_update)
connect_auto_add(hass, discovery_info, sensor_update)
class RfxtrxSensor(RfxtrxEntity):

View File

@@ -8,13 +8,12 @@ from homeassistant.const import CONF_DEVICES, STATE_ON
from homeassistant.core import callback
from . import (
CONF_AUTOMATIC_ADD,
CONF_DATA_BITS,
CONF_SIGNAL_REPETITIONS,
DEFAULT_SIGNAL_REPETITIONS,
DOMAIN,
SIGNAL_EVENT,
RfxtrxCommandEntity,
connect_auto_add,
get_device_id,
get_rfx_object,
)
@@ -92,8 +91,7 @@ async def async_setup_entry(
async_add_entities([entity])
# Subscribe to main RFXtrx events
if discovery_info[CONF_AUTOMATIC_ADD]:
hass.helpers.dispatcher.async_dispatcher_connect(SIGNAL_EVENT, switch_update)
connect_auto_add(hass, discovery_info, switch_update)
class RfxtrxSwitch(RfxtrxCommandEntity, SwitchEntity):

View File

@@ -123,9 +123,6 @@ class PwmSimpleLed(LightEntity, RestoreEntity):
self._brightness = last_state.attributes.get(
"brightness", DEFAULT_BRIGHTNESS
)
self._led.set(
is_on=self._is_on, brightness=_from_hass_brightness(self._brightness)
)
@property
def should_poll(self):
@@ -199,7 +196,6 @@ class PwmRgbLed(PwmSimpleLed):
last_state = await self.async_get_last_state()
if last_state:
self._color = last_state.attributes.get("hs_color", DEFAULT_COLOR)
self._led.set(color=_from_hass_color(self._color))
@property
def hs_color(self):

View File

@@ -2,6 +2,6 @@
"domain": "rpi_gpio_pwm",
"name": "pigpio Daemon PWM LED",
"documentation": "https://www.home-assistant.io/integrations/rpi_gpio_pwm",
"requirements": ["pwmled==1.6.6"],
"codeowners": []
"requirements": ["pwmled==1.6.7"],
"codeowners": ["@soldag"]
}

View File

@@ -3,6 +3,7 @@ import asyncio
from uuid import UUID
from simplipy import API
from simplipy.entity import EntityTypes
from simplipy.errors import EndpointUnavailable, InvalidCredentialsError, SimplipyError
from simplipy.websocket import (
EVENT_CAMERA_MOTION_DETECTED,
@@ -590,6 +591,13 @@ class SimpliSafeEntity(CoordinatorEntity):
else:
self._serial = system.serial
try:
sensor_type = EntityTypes(
simplisafe.initial_event_to_use[system.system_id].get("sensorType")
)
except ValueError:
sensor_type = EntityTypes.unknown
self._attrs = {
ATTR_LAST_EVENT_INFO: simplisafe.initial_event_to_use[system.system_id].get(
"info"
@@ -597,9 +605,7 @@ class SimpliSafeEntity(CoordinatorEntity):
ATTR_LAST_EVENT_SENSOR_NAME: simplisafe.initial_event_to_use[
system.system_id
].get("sensorName"),
ATTR_LAST_EVENT_SENSOR_TYPE: simplisafe.initial_event_to_use[
system.system_id
].get("sensorType"),
ATTR_LAST_EVENT_SENSOR_TYPE: sensor_type.name,
ATTR_LAST_EVENT_TIMESTAMP: simplisafe.initial_event_to_use[
system.system_id
].get("eventTimestamp"),
@@ -724,3 +730,23 @@ class SimpliSafeEntity(CoordinatorEntity):
@callback
def async_update_from_websocket_event(self, event):
"""Update the entity with the provided websocket event."""
class SimpliSafeBaseSensor(SimpliSafeEntity):
"""Define a SimpliSafe base (binary) sensor."""
def __init__(self, simplisafe, system, sensor):
"""Initialize."""
super().__init__(simplisafe, system, sensor.name, serial=sensor.serial)
self._device_info["identifiers"] = {(DOMAIN, sensor.serial)}
self._device_info["model"] = sensor.type.name
self._device_info["name"] = sensor.name
self._sensor = sensor
self._sensor_type_human_name = " ".join(
[w.title() for w in self._sensor.type.name.split("_")]
)
@property
def name(self):
"""Return the name of the sensor."""
return f"{self._system.address} {self._name} {self._sensor_type_human_name}"

View File

@@ -159,7 +159,7 @@ class SimpliSafeAlarm(SimpliSafeEntity, AlarmControlPanelEntity):
try:
await self._system.set_off()
except SimplipyError as err:
LOGGER.error('Error while disarming "%s": %s', self._system.name, err)
LOGGER.error('Error while disarming "%s": %s', self._system.system_id, err)
return
self._state = STATE_ALARM_DISARMED
@@ -172,7 +172,9 @@ class SimpliSafeAlarm(SimpliSafeEntity, AlarmControlPanelEntity):
try:
await self._system.set_home()
except SimplipyError as err:
LOGGER.error('Error while arming "%s" (home): %s', self._system.name, err)
LOGGER.error(
'Error while arming "%s" (home): %s', self._system.system_id, err
)
return
self._state = STATE_ALARM_ARMED_HOME
@@ -185,7 +187,9 @@ class SimpliSafeAlarm(SimpliSafeEntity, AlarmControlPanelEntity):
try:
await self._system.set_away()
except SimplipyError as err:
LOGGER.error('Error while arming "%s" (away): %s', self._system.name, err)
LOGGER.error(
'Error while arming "%s" (away): %s', self._system.system_id, err
)
return
self._state = STATE_ALARM_ARMING

View File

@@ -6,42 +6,32 @@ from homeassistant.components.binary_sensor import (
DEVICE_CLASS_DOOR,
DEVICE_CLASS_GAS,
DEVICE_CLASS_MOISTURE,
DEVICE_CLASS_MOTION,
DEVICE_CLASS_SAFETY,
DEVICE_CLASS_SMOKE,
BinarySensorEntity,
)
from homeassistant.core import callback
from . import SimpliSafeEntity
from . import SimpliSafeBaseSensor
from .const import DATA_CLIENT, DOMAIN, LOGGER
SUPPORTED_BATTERY_SENSOR_TYPES = [
EntityTypes.carbon_monoxide,
EntityTypes.entry,
EntityTypes.leak,
EntityTypes.lock,
EntityTypes.lock_keypad,
EntityTypes.smoke,
EntityTypes.temperature,
]
SUPPORTED_SENSOR_TYPES = [
EntityTypes.entry,
EntityTypes.carbon_monoxide,
EntityTypes.smoke,
EntityTypes.leak,
]
HA_SENSOR_TYPES = {
EntityTypes.entry: DEVICE_CLASS_DOOR,
TRIGGERED_SENSOR_TYPES = {
EntityTypes.carbon_monoxide: DEVICE_CLASS_GAS,
EntityTypes.smoke: DEVICE_CLASS_SMOKE,
EntityTypes.entry: DEVICE_CLASS_DOOR,
EntityTypes.glass_break: DEVICE_CLASS_SAFETY,
EntityTypes.leak: DEVICE_CLASS_MOISTURE,
}
SENSOR_MODELS = {
EntityTypes.entry: "Entry Sensor",
EntityTypes.carbon_monoxide: "Carbon Monoxide Detector",
EntityTypes.smoke: "Smoke Detector",
EntityTypes.leak: "Water Sensor",
EntityTypes.motion: DEVICE_CLASS_MOTION,
EntityTypes.smoke: DEVICE_CLASS_SMOKE,
}
@@ -56,37 +46,34 @@ async def async_setup_entry(hass, entry, async_add_entities):
continue
for sensor in system.sensors.values():
if sensor.type in SUPPORTED_SENSOR_TYPES:
sensors.append(SimpliSafeBinarySensor(simplisafe, system, sensor))
if sensor.type in TRIGGERED_SENSOR_TYPES:
sensors.append(
TriggeredBinarySensor(
simplisafe,
system,
sensor,
TRIGGERED_SENSOR_TYPES[sensor.type],
)
)
if sensor.type in SUPPORTED_BATTERY_SENSOR_TYPES:
sensors.append(SimpliSafeSensorBattery(simplisafe, system, sensor))
sensors.append(BatteryBinarySensor(simplisafe, system, sensor))
async_add_entities(sensors)
class SimpliSafeBinarySensor(SimpliSafeEntity, BinarySensorEntity):
"""Define a SimpliSafe binary sensor entity."""
class TriggeredBinarySensor(SimpliSafeBaseSensor, BinarySensorEntity):
"""Define a binary sensor related to whether an entity has been triggered."""
def __init__(self, simplisafe, system, sensor):
def __init__(self, simplisafe, system, sensor, device_class):
"""Initialize."""
super().__init__(simplisafe, system, sensor.name, serial=sensor.serial)
self._system = system
self._sensor = sensor
super().__init__(simplisafe, system, sensor)
self._device_class = device_class
self._is_on = False
@property
def device_class(self):
"""Return type of sensor."""
return HA_SENSOR_TYPES[self._sensor.type]
@property
def device_info(self):
"""Return device registry information for this entity."""
info = super().device_info
info["identifiers"] = {(DOMAIN, self._sensor.serial)}
info["model"] = SENSOR_MODELS[self._sensor.type]
info["name"] = self._sensor.name
return info
return self._device_class
@property
def is_on(self):
@@ -99,19 +86,14 @@ class SimpliSafeBinarySensor(SimpliSafeEntity, BinarySensorEntity):
self._is_on = self._sensor.triggered
class SimpliSafeSensorBattery(SimpliSafeEntity, BinarySensorEntity):
class BatteryBinarySensor(SimpliSafeBaseSensor, BinarySensorEntity):
"""Define a SimpliSafe battery binary sensor entity."""
def __init__(self, simplisafe, system, sensor):
"""Initialize."""
super().__init__(simplisafe, system, sensor.name, serial=sensor.serial)
self._sensor = sensor
super().__init__(simplisafe, system, sensor)
self._is_low = False
self._device_info["identifiers"] = {(DOMAIN, sensor.serial)}
self._device_info["model"] = SENSOR_MODELS[sensor.type]
self._device_info["name"] = sensor.name
@property
def device_class(self):
"""Return type of sensor."""

View File

@@ -4,7 +4,7 @@ from simplipy.entity import EntityTypes
from homeassistant.const import DEVICE_CLASS_TEMPERATURE, TEMP_FAHRENHEIT
from homeassistant.core import callback
from . import SimpliSafeEntity
from . import SimpliSafeBaseSensor
from .const import DATA_CLIENT, DOMAIN, LOGGER
@@ -25,19 +25,14 @@ async def async_setup_entry(hass, entry, async_add_entities):
async_add_entities(sensors)
class SimplisafeFreezeSensor(SimpliSafeEntity):
class SimplisafeFreezeSensor(SimpliSafeBaseSensor):
"""Define a SimpliSafe freeze sensor entity."""
def __init__(self, simplisafe, system, sensor):
"""Initialize."""
super().__init__(simplisafe, system, sensor.name, serial=sensor.serial)
self._sensor = sensor
super().__init__(simplisafe, system, sensor)
self._state = None
self._device_info["identifiers"] = {(DOMAIN, sensor.serial)}
self._device_info["model"] = "Freeze Sensor"
self._device_info["name"] = sensor.name
@property
def device_class(self):
"""Return type of sensor."""

View File

@@ -258,10 +258,9 @@ class SynoApi:
self._entry.data[CONF_PASSWORD],
self._entry.data[CONF_SSL],
timeout=self._entry.options.get(CONF_TIMEOUT),
device_token=self._entry.data.get("device_token"),
)
await self._hass.async_add_executor_job(
self.dsm.login, self._entry.data.get("device_token")
)
await self._hass.async_add_executor_job(self.dsm.login)
self._with_surveillance_station = bool(
self.dsm.apis.get(SynoSurveillanceStation.CAMERA_API_KEY)

View File

@@ -128,6 +128,11 @@ class TasmotaLight(
white_value = float(attributes["white_value"])
percent_white = white_value / TASMOTA_BRIGHTNESS_MAX
self._white_value = percent_white * 255
if self._white_value == 0:
self._color_temp = None
self._white_value = None
if self._white_value is not None and self._white_value > 0:
self._hs = None
self.async_write_ha_state()
@property

View File

@@ -3,7 +3,7 @@
"name": "Tasmota (beta)",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/tasmota",
"requirements": ["hatasmota==0.0.25"],
"requirements": ["hatasmota==0.0.25.1"],
"dependencies": ["mqtt"],
"mqtt": ["tasmota/discovery/#"],
"codeowners": ["@emontnemery"]

View File

@@ -348,9 +348,11 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle zeroconf discovery."""
assert self.hass
discovery_info[
CONF_HOST
] = f"{discovery_info[CONF_HOST]}:{discovery_info[CONF_PORT]}"
# If host already has port, no need to add it again
if ":" not in discovery_info[CONF_HOST]:
discovery_info[
CONF_HOST
] = f"{discovery_info[CONF_HOST]}:{discovery_info[CONF_PORT]}"
# Set default name to discovered device name by stripping zeroconf service
# (`type`) from `name`

View File

@@ -1,7 +1,7 @@
"""Constants used by Home Assistant components."""
MAJOR_VERSION = 0
MINOR_VERSION = 117
PATCH_VERSION = "2"
PATCH_VERSION = "6"
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
__version__ = f"{__short_version__}.{PATCH_VERSION}"
REQUIRED_PYTHON_VER = (3, 7, 1)

View File

@@ -8,7 +8,7 @@ attrs==19.3.0
bcrypt==3.1.7
certifi>=2020.6.20
ciso8601==2.1.3
cryptography==3.2.0
cryptography==3.2
defusedxml==0.6.0
distro==1.5.0
emoji==0.5.4

View File

@@ -12,7 +12,7 @@ httpx==0.16.1
importlib-metadata==1.6.0;python_version<'3.8'
jinja2>=2.11.2
PyJWT==1.7.1
cryptography==3.2.0
cryptography==3.2
pip>=8.0.3
python-slugify==4.0.1
pytz>=2020.1

View File

@@ -342,7 +342,7 @@ beautifulsoup4==4.9.1
bellows==0.20.3
# homeassistant.components.bmw_connected_drive
bimmer_connected==0.7.8
bimmer_connected==0.7.12
# homeassistant.components.bizkaibus
bizkaibus==0.1.1
@@ -619,7 +619,7 @@ freesms==0.1.2
fritzconnection==1.2.0
# homeassistant.components.google_translate
gTTS-token==1.1.3
gTTS-token==1.1.4
# homeassistant.components.garmin_connect
garminconnect==0.1.13
@@ -696,7 +696,7 @@ gpiozero==1.5.1
gps3==0.33.3
# homeassistant.components.gree
greeclimate==0.9.2
greeclimate==0.9.5
# homeassistant.components.greeneye_monitor
greeneye_monitor==2.1
@@ -732,7 +732,7 @@ hass-nabucasa==0.37.1
hass_splunk==0.1.1
# homeassistant.components.tasmota
hatasmota==0.0.25
hatasmota==0.0.25.1
# homeassistant.components.jewish_calendar
hdate==0.9.12
@@ -1124,7 +1124,7 @@ pizzapi==0.0.3
plexapi==4.1.1
# homeassistant.components.plex
plexauth==0.0.5
plexauth==0.0.6
# homeassistant.components.plex
plexwebsocket==0.0.12
@@ -1182,7 +1182,7 @@ pushbullet.py==0.11.0
pushover_complete==1.1.1
# homeassistant.components.rpi_gpio_pwm
pwmled==1.6.6
pwmled==1.6.7
# homeassistant.components.august
py-august==0.25.0
@@ -1252,7 +1252,7 @@ pyaehw4a1==0.3.9
pyaftership==0.1.2
# homeassistant.components.airvisual
pyairvisual==5.0.3
pyairvisual==5.0.4
# homeassistant.components.almond
pyalmond==0.0.2
@@ -1264,7 +1264,7 @@ pyarlo==0.2.3
pyatag==0.3.4.4
# homeassistant.components.netatmo
pyatmo==4.1.0
pyatmo==4.2.0
# homeassistant.components.atome
pyatome==0.1.1

View File

@@ -302,7 +302,7 @@ fnvhash==0.1.0
foobot_async==0.3.2
# homeassistant.components.google_translate
gTTS-token==1.1.3
gTTS-token==1.1.4
# homeassistant.components.garmin_connect
garminconnect==0.1.13
@@ -352,7 +352,7 @@ google-cloud-pubsub==0.39.1
google-nest-sdm==0.1.6
# homeassistant.components.gree
greeclimate==0.9.2
greeclimate==0.9.5
# homeassistant.components.griddy
griddypower==0.1.0
@@ -367,7 +367,7 @@ hangups==0.4.11
hass-nabucasa==0.37.1
# homeassistant.components.tasmota
hatasmota==0.0.25
hatasmota==0.0.25.1
# homeassistant.components.jewish_calendar
hdate==0.9.12
@@ -541,7 +541,7 @@ pillow==7.2.0
plexapi==4.1.1
# homeassistant.components.plex
plexauth==0.0.5
plexauth==0.0.6
# homeassistant.components.plex
plexwebsocket==0.0.12
@@ -615,7 +615,7 @@ py_nextbusnext==0.1.4
pyaehw4a1==0.3.9
# homeassistant.components.airvisual
pyairvisual==5.0.3
pyairvisual==5.0.4
# homeassistant.components.almond
pyalmond==0.0.2
@@ -627,7 +627,7 @@ pyarlo==0.2.3
pyatag==0.3.4.4
# homeassistant.components.netatmo
pyatmo==4.1.0
pyatmo==4.2.0
# homeassistant.components.blackbird
pyblackbird==0.5

View File

@@ -44,7 +44,7 @@ REQUIRES = [
"jinja2>=2.11.2",
"PyJWT==1.7.1",
# PyJWT has loose dependency. We want the latest one.
"cryptography==3.2.0",
"cryptography==3.2",
"pip>=8.0.3",
"python-slugify==4.0.1",
"pytz>=2020.1",

View File

@@ -116,7 +116,7 @@ async def test_setup_minimum_resource_template(hass):
{
"binary_sensor": {
"platform": "rest",
"resource_template": "http://localhost",
"resource_template": "{% set url = 'http://localhost' %}{{ url }}",
}
},
)

View File

@@ -102,7 +102,7 @@ async def test_setup_minimum_resource_template(hass):
{
"sensor": {
"platform": "rest",
"resource_template": "http://localhost",
"resource_template": "{% set url = 'http://localhost' %}{{ url }}",
}
},
)

View File

@@ -58,6 +58,44 @@ DEFAULT_CONFIG = {
}
DEFAULT_CONFIG_9_0_0_4 = {
"ip": "192.168.15.10",
"dn": "Tasmota",
"fn": ["Test", "Beer", "Milk", "Four", None],
"hn": "tasmota_49A3BC-0956",
"if": 0, # iFan
"lk": 1, # RGB + white channels linked to a single light
"mac": "00000049A3BC",
"md": "Sonoff Basic",
"ofln": "Offline",
"onln": "Online",
"state": ["OFF", "ON", "TOGGLE", "HOLD"],
"sw": "8.4.0.2",
"swn": [None, None, None, None, None],
"t": "tasmota_49A3BC",
"ft": "%topic%/%prefix%/",
"tp": ["cmnd", "stat", "tele"],
"rl": [0, 0, 0, 0, 0, 0, 0, 0],
"swc": [-1, -1, -1, -1, -1, -1, -1, -1],
"btn": [0, 0, 0, 0],
"so": {
"4": 0, # Return MQTT response as RESULT or %COMMAND%
"11": 0, # Swap button single and double press functionality
"13": 0, # Allow immediate action on single button press
"17": 1, # Show Color string as hex or comma-separated
"20": 0, # Update of Dimmer/Color/CT without turning power on
"30": 0, # Enforce Home Assistant auto-discovery as light
"68": 0, # Multi-channel PWM instead of a single light
"73": 0, # Enable Buttons decoupling and send multi-press and hold MQTT messages
"82": 0, # Reduce the CT range from 153..500 to 200.380
"114": 0, # Enable sending switch MQTT messages
},
"ty": 0, # Tuya MCU
"lt_st": 0,
"ver": 1,
}
async def help_test_availability_when_connection_lost(
hass,
mqtt_client_mock,

View File

@@ -6,7 +6,7 @@ from homeassistant.components.tasmota.const import DEFAULT_PREFIX
from homeassistant.components.tasmota.discovery import ALREADY_DISCOVERED
from .conftest import setup_tasmota_helper
from .test_common import DEFAULT_CONFIG
from .test_common import DEFAULT_CONFIG, DEFAULT_CONFIG_9_0_0_4
from tests.async_mock import patch
from tests.common import async_fire_mqtt_message
@@ -132,6 +132,29 @@ async def test_device_discover(
assert device_entry.sw_version == config["sw"]
async def test_device_discover_deprecated(
hass, mqtt_mock, caplog, device_reg, entity_reg, setup_tasmota
):
"""Test setting up a device with deprecated discovery message."""
config = copy.deepcopy(DEFAULT_CONFIG_9_0_0_4)
mac = config["mac"]
async_fire_mqtt_message(
hass,
f"{DEFAULT_PREFIX}/{mac}/config",
json.dumps(config),
)
await hass.async_block_till_done()
# Verify device and registry entries are created
device_entry = device_reg.async_get_device(set(), {("mac", mac)})
assert device_entry is not None
assert device_entry.manufacturer == "Tasmota"
assert device_entry.model == config["md"]
assert device_entry.name == config["dn"]
assert device_entry.sw_version == config["sw"]
async def test_device_update(
hass, mqtt_mock, caplog, device_reg, entity_reg, setup_tasmota
):

View File

@@ -432,6 +432,8 @@ async def test_controlling_state_via_mqtt_rgbww(hass, mqtt_mock, setup_tasmota):
state = hass.states.get("light.test")
assert state.state == STATE_ON
assert state.attributes.get("white_value") == 127.5
# Setting white > 0 should clear the color
assert not state.attributes.get("rgb_color")
async_fire_mqtt_message(
hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"ON","CT":300}'
@@ -440,6 +442,15 @@ async def test_controlling_state_via_mqtt_rgbww(hass, mqtt_mock, setup_tasmota):
assert state.state == STATE_ON
assert state.attributes.get("color_temp") == 300
async_fire_mqtt_message(
hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"ON","White":0}'
)
state = hass.states.get("light.test")
assert state.state == STATE_ON
# Setting white to 0 should clear the white_value and color_temp
assert not state.attributes.get("white_value")
assert not state.attributes.get("color_temp")
async_fire_mqtt_message(
hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"ON","Scheme":3}'
)

View File

@@ -27,6 +27,7 @@ from homeassistant.const import (
CONF_HOST,
CONF_NAME,
CONF_PIN,
CONF_PORT,
)
from homeassistant.helpers.typing import HomeAssistantType
@@ -777,6 +778,35 @@ async def test_zeroconf_flow_already_configured(
assert result["reason"] == "already_configured"
async def test_zeroconf_flow_with_port_in_host(
hass: HomeAssistantType,
vizio_connect: pytest.fixture,
vizio_bypass_setup: pytest.fixture,
vizio_guess_device_type: pytest.fixture,
) -> None:
"""Test entity is already configured during zeroconf setup when port is in host."""
entry = MockConfigEntry(
domain=DOMAIN,
data=MOCK_SPEAKER_CONFIG,
options={CONF_VOLUME_STEP: VOLUME_STEP},
unique_id=UNIQUE_ID,
)
entry.add_to_hass(hass)
# Try rediscovering same device, this time with port already in host
discovery_info = MOCK_ZEROCONF_SERVICE_INFO.copy()
discovery_info[
CONF_HOST
] = f"{discovery_info[CONF_HOST]}:{discovery_info[CONF_PORT]}"
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_ZEROCONF}, data=discovery_info
)
# Flow should abort because device is already setup
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
assert result["reason"] == "already_configured"
async def test_zeroconf_dupe_fail(
hass: HomeAssistantType,
vizio_connect: pytest.fixture,