mirror of
https://github.com/home-assistant/core.git
synced 2025-07-28 15:47:12 +00:00
Merge pull request #35221 from home-assistant/rc
This commit is contained in:
commit
d2179e5321
@ -24,10 +24,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
"""Set up the Canary alarms."""
|
"""Set up the Canary alarms."""
|
||||||
data = hass.data[DATA_CANARY]
|
data = hass.data[DATA_CANARY]
|
||||||
devices = []
|
devices = [CanaryAlarm(data, location.location_id) for location in data.locations]
|
||||||
|
|
||||||
for location in data.locations:
|
|
||||||
devices.append(CanaryAlarm(data, location.location_id))
|
|
||||||
|
|
||||||
add_entities(devices, True)
|
add_entities(devices, True)
|
||||||
|
|
||||||
|
@ -29,6 +29,9 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
|||||||
|
|
||||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
"""Set up the Canary sensors."""
|
"""Set up the Canary sensors."""
|
||||||
|
if discovery_info is not None:
|
||||||
|
return
|
||||||
|
|
||||||
data = hass.data[DATA_CANARY]
|
data = hass.data[DATA_CANARY]
|
||||||
devices = []
|
devices = []
|
||||||
|
|
||||||
|
@ -259,6 +259,9 @@ class HueLight(Light):
|
|||||||
else:
|
else:
|
||||||
bri = self.light.state.get("bri")
|
bri = self.light.state.get("bri")
|
||||||
|
|
||||||
|
if bri is None:
|
||||||
|
return bri
|
||||||
|
|
||||||
return hue_brightness_to_hass(bri)
|
return hue_brightness_to_hass(bri)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -186,7 +186,7 @@ class IcloudAccount:
|
|||||||
DEVICE_STATUS_CODES.get(list(api_devices)[0][DEVICE_STATUS]) == "pending"
|
DEVICE_STATUS_CODES.get(list(api_devices)[0][DEVICE_STATUS]) == "pending"
|
||||||
and not self._retried_fetch
|
and not self._retried_fetch
|
||||||
):
|
):
|
||||||
_LOGGER.warning("Pending devices, trying again in 15s")
|
_LOGGER.debug("Pending devices, trying again in 15s")
|
||||||
self._fetch_interval = 0.25
|
self._fetch_interval = 0.25
|
||||||
self._retried_fetch = True
|
self._retried_fetch = True
|
||||||
else:
|
else:
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
"name": "Apple iCloud",
|
"name": "Apple iCloud",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/icloud",
|
"documentation": "https://www.home-assistant.io/integrations/icloud",
|
||||||
"requirements": ["pyicloud==0.9.6.1"],
|
"requirements": ["pyicloud==0.9.7"],
|
||||||
"codeowners": ["@Quentame"]
|
"codeowners": ["@Quentame"]
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,6 @@ async def async_setup_entry(hass, config_entry):
|
|||||||
address=config_entry.data[CONF_HOST],
|
address=config_entry.data[CONF_HOST],
|
||||||
blid=config_entry.data[CONF_BLID],
|
blid=config_entry.data[CONF_BLID],
|
||||||
password=config_entry.data[CONF_PASSWORD],
|
password=config_entry.data[CONF_PASSWORD],
|
||||||
cert_name=config_entry.data[CONF_CERT],
|
|
||||||
continuous=config_entry.options[CONF_CONTINUOUS],
|
continuous=config_entry.options[CONF_CONTINUOUS],
|
||||||
delay=config_entry.options[CONF_DELAY],
|
delay=config_entry.options[CONF_DELAY],
|
||||||
)
|
)
|
||||||
|
@ -11,11 +11,9 @@ from homeassistant.core import callback
|
|||||||
from . import CannotConnect, async_connect_or_timeout, async_disconnect_or_timeout
|
from . import CannotConnect, async_connect_or_timeout, async_disconnect_or_timeout
|
||||||
from .const import (
|
from .const import (
|
||||||
CONF_BLID,
|
CONF_BLID,
|
||||||
CONF_CERT,
|
|
||||||
CONF_CONTINUOUS,
|
CONF_CONTINUOUS,
|
||||||
CONF_DELAY,
|
CONF_DELAY,
|
||||||
CONF_NAME,
|
CONF_NAME,
|
||||||
DEFAULT_CERT,
|
|
||||||
DEFAULT_CONTINUOUS,
|
DEFAULT_CONTINUOUS,
|
||||||
DEFAULT_DELAY,
|
DEFAULT_DELAY,
|
||||||
ROOMBA_SESSION,
|
ROOMBA_SESSION,
|
||||||
@ -27,7 +25,6 @@ DATA_SCHEMA = vol.Schema(
|
|||||||
vol.Required(CONF_HOST): str,
|
vol.Required(CONF_HOST): str,
|
||||||
vol.Required(CONF_BLID): str,
|
vol.Required(CONF_BLID): str,
|
||||||
vol.Required(CONF_PASSWORD): str,
|
vol.Required(CONF_PASSWORD): str,
|
||||||
vol.Optional(CONF_CERT, default=DEFAULT_CERT): str,
|
|
||||||
vol.Optional(CONF_CONTINUOUS, default=DEFAULT_CONTINUOUS): bool,
|
vol.Optional(CONF_CONTINUOUS, default=DEFAULT_CONTINUOUS): bool,
|
||||||
vol.Optional(CONF_DELAY, default=DEFAULT_DELAY): int,
|
vol.Optional(CONF_DELAY, default=DEFAULT_DELAY): int,
|
||||||
}
|
}
|
||||||
@ -45,7 +42,6 @@ async def validate_input(hass: core.HomeAssistant, data):
|
|||||||
address=data[CONF_HOST],
|
address=data[CONF_HOST],
|
||||||
blid=data[CONF_BLID],
|
blid=data[CONF_BLID],
|
||||||
password=data[CONF_PASSWORD],
|
password=data[CONF_PASSWORD],
|
||||||
cert_name=data[CONF_CERT],
|
|
||||||
continuous=data[CONF_CONTINUOUS],
|
continuous=data[CONF_CONTINUOUS],
|
||||||
delay=data[CONF_DELAY],
|
delay=data[CONF_DELAY],
|
||||||
)
|
)
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"name": "iRobot Roomba",
|
"name": "iRobot Roomba",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/roomba",
|
"documentation": "https://www.home-assistant.io/integrations/roomba",
|
||||||
"requirements": ["roombapy==1.5.2"],
|
"requirements": ["roombapy==1.5.3"],
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"codeowners": ["@pschmitt", "@cyr-ius", "@shenxn"]
|
"codeowners": ["@pschmitt", "@cyr-ius", "@shenxn"]
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
"host": "Hostname or IP Address",
|
"host": "Hostname or IP Address",
|
||||||
"blid": "BLID",
|
"blid": "BLID",
|
||||||
"password": "Password",
|
"password": "Password",
|
||||||
"certificate": "Certificate",
|
|
||||||
"continuous": "Continuous",
|
"continuous": "Continuous",
|
||||||
"delay": "Delay"
|
"delay": "Delay"
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
|||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_DISKS,
|
CONF_DISKS,
|
||||||
CONF_HOST,
|
CONF_HOST,
|
||||||
|
CONF_MAC,
|
||||||
CONF_PASSWORD,
|
CONF_PASSWORD,
|
||||||
CONF_PORT,
|
CONF_PORT,
|
||||||
CONF_SSL,
|
CONF_SSL,
|
||||||
@ -77,6 +78,13 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry):
|
|||||||
hass.data.setdefault(DOMAIN, {})
|
hass.data.setdefault(DOMAIN, {})
|
||||||
hass.data[DOMAIN][entry.unique_id] = api
|
hass.data[DOMAIN][entry.unique_id] = api
|
||||||
|
|
||||||
|
# For SSDP compat
|
||||||
|
if not entry.data.get(CONF_MAC):
|
||||||
|
network = await hass.async_add_executor_job(getattr, api.dsm, "network")
|
||||||
|
hass.config_entries.async_update_entry(
|
||||||
|
entry, data={**entry.data, CONF_MAC: network.macs}
|
||||||
|
)
|
||||||
|
|
||||||
hass.async_create_task(
|
hass.async_create_task(
|
||||||
hass.config_entries.async_forward_entry_setup(entry, "sensor")
|
hass.config_entries.async_forward_entry_setup(entry, "sensor")
|
||||||
)
|
)
|
||||||
@ -115,7 +123,7 @@ class SynoApi:
|
|||||||
self._device_token = device_token
|
self._device_token = device_token
|
||||||
self.temp_unit = temp_unit
|
self.temp_unit = temp_unit
|
||||||
|
|
||||||
self._dsm: SynologyDSM = None
|
self.dsm: SynologyDSM = None
|
||||||
self.information: SynoDSMInformation = None
|
self.information: SynoDSMInformation = None
|
||||||
self.utilisation: SynoCoreUtilization = None
|
self.utilisation: SynoCoreUtilization = None
|
||||||
self.storage: SynoStorage = None
|
self.storage: SynoStorage = None
|
||||||
@ -129,7 +137,7 @@ class SynoApi:
|
|||||||
|
|
||||||
async def async_setup(self):
|
async def async_setup(self):
|
||||||
"""Start interacting with the NAS."""
|
"""Start interacting with the NAS."""
|
||||||
self._dsm = SynologyDSM(
|
self.dsm = SynologyDSM(
|
||||||
self._host,
|
self._host,
|
||||||
self._port,
|
self._port,
|
||||||
self._username,
|
self._username,
|
||||||
@ -147,9 +155,9 @@ class SynoApi:
|
|||||||
|
|
||||||
def _fetch_device_configuration(self):
|
def _fetch_device_configuration(self):
|
||||||
"""Fetch initial device config."""
|
"""Fetch initial device config."""
|
||||||
self.information = self._dsm.information
|
self.information = self.dsm.information
|
||||||
self.utilisation = self._dsm.utilisation
|
self.utilisation = self.dsm.utilisation
|
||||||
self.storage = self._dsm.storage
|
self.storage = self.dsm.storage
|
||||||
|
|
||||||
async def async_unload(self):
|
async def async_unload(self):
|
||||||
"""Stop interacting with the NAS and prepare for removal from hass."""
|
"""Stop interacting with the NAS and prepare for removal from hass."""
|
||||||
@ -157,5 +165,5 @@ class SynoApi:
|
|||||||
|
|
||||||
async def update(self, now=None):
|
async def update(self, now=None):
|
||||||
"""Update function for updating API information."""
|
"""Update function for updating API information."""
|
||||||
await self._hass.async_add_executor_job(self._dsm.update)
|
await self._hass.async_add_executor_job(self.dsm.update)
|
||||||
async_dispatcher_send(self._hass, self.signal_sensor_update)
|
async_dispatcher_send(self._hass, self.signal_sensor_update)
|
||||||
|
@ -17,6 +17,7 @@ from homeassistant.components import ssdp
|
|||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_DISKS,
|
CONF_DISKS,
|
||||||
CONF_HOST,
|
CONF_HOST,
|
||||||
|
CONF_MAC,
|
||||||
CONF_NAME,
|
CONF_NAME,
|
||||||
CONF_PASSWORD,
|
CONF_PASSWORD,
|
||||||
CONF_PORT,
|
CONF_PORT,
|
||||||
@ -145,6 +146,7 @@ class SynologyDSMFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
CONF_SSL: use_ssl,
|
CONF_SSL: use_ssl,
|
||||||
CONF_USERNAME: username,
|
CONF_USERNAME: username,
|
||||||
CONF_PASSWORD: password,
|
CONF_PASSWORD: password,
|
||||||
|
CONF_MAC: api.network.macs,
|
||||||
}
|
}
|
||||||
if otp_code:
|
if otp_code:
|
||||||
config_data["device_token"] = api.device_token
|
config_data["device_token"] = api.device_token
|
||||||
@ -162,16 +164,11 @@ class SynologyDSMFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
discovery_info[ssdp.ATTR_UPNP_FRIENDLY_NAME].split("(", 1)[0].strip()
|
discovery_info[ssdp.ATTR_UPNP_FRIENDLY_NAME].split("(", 1)[0].strip()
|
||||||
)
|
)
|
||||||
|
|
||||||
if self._host_already_configured(parsed_url.hostname):
|
# Synology NAS can broadcast on multiple IP addresses, since they can be connected to multiple ethernets.
|
||||||
|
# The serial of the NAS is actually its MAC address.
|
||||||
|
if self._mac_already_configured(discovery_info[ssdp.ATTR_UPNP_SERIAL].upper()):
|
||||||
return self.async_abort(reason="already_configured")
|
return self.async_abort(reason="already_configured")
|
||||||
|
|
||||||
if ssdp.ATTR_UPNP_SERIAL in discovery_info:
|
|
||||||
# Synology can broadcast on multiple IP addresses
|
|
||||||
await self.async_set_unique_id(
|
|
||||||
discovery_info[ssdp.ATTR_UPNP_SERIAL].upper()
|
|
||||||
)
|
|
||||||
self._abort_if_unique_id_configured()
|
|
||||||
|
|
||||||
self.discovered_conf = {
|
self.discovered_conf = {
|
||||||
CONF_NAME: friendly_name,
|
CONF_NAME: friendly_name,
|
||||||
CONF_HOST: parsed_url.hostname,
|
CONF_HOST: parsed_url.hostname,
|
||||||
@ -205,12 +202,14 @@ class SynologyDSMFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
return await self.async_step_user(user_input)
|
return await self.async_step_user(user_input)
|
||||||
|
|
||||||
def _host_already_configured(self, hostname):
|
def _mac_already_configured(self, mac):
|
||||||
"""See if we already have a host matching user input configured."""
|
"""See if we already have configured a NAS with this MAC address."""
|
||||||
existing_hosts = {
|
existing_macs = [
|
||||||
entry.data[CONF_HOST] for entry in self._async_current_entries()
|
mac.replace("-", "")
|
||||||
}
|
for entry in self._async_current_entries()
|
||||||
return hostname in existing_hosts
|
for mac in entry.data.get(CONF_MAC, [])
|
||||||
|
]
|
||||||
|
return mac in existing_macs
|
||||||
|
|
||||||
|
|
||||||
def _login_and_fetch_syno_info(api, otp_code):
|
def _login_and_fetch_syno_info(api, otp_code):
|
||||||
@ -221,10 +220,11 @@ def _login_and_fetch_syno_info(api, otp_code):
|
|||||||
storage = api.storage
|
storage = api.storage
|
||||||
|
|
||||||
if (
|
if (
|
||||||
api.information.serial is None
|
not api.information.serial
|
||||||
or utilisation.cpu_user_load is None
|
or utilisation.cpu_user_load is None
|
||||||
or storage.disks_ids is None
|
or not storage.disks_ids
|
||||||
or storage.volumes_ids is None
|
or not storage.volumes_ids
|
||||||
|
or not api.network.macs
|
||||||
):
|
):
|
||||||
raise InvalidData
|
raise InvalidData
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ class SynoNasUtilSensor(SynoNasSensor):
|
|||||||
attr = getattr(self._api.utilisation, self.sensor_type)
|
attr = getattr(self._api.utilisation, self.sensor_type)
|
||||||
if callable(attr):
|
if callable(attr):
|
||||||
attr = attr()
|
attr = attr()
|
||||||
if not attr:
|
if attr is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Data (RAM)
|
# Data (RAM)
|
||||||
@ -173,7 +173,7 @@ class SynoNasStorageSensor(SynoNasSensor):
|
|||||||
def state(self):
|
def state(self):
|
||||||
"""Return the state."""
|
"""Return the state."""
|
||||||
attr = getattr(self._api.storage, self.sensor_type)(self.monitored_device)
|
attr = getattr(self._api.storage, self.sensor_type)(self.monitored_device)
|
||||||
if not attr:
|
if attr is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Data (disk space)
|
# Data (disk space)
|
||||||
|
@ -95,7 +95,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
|
|||||||
|
|
||||||
platform.async_register_entity_service(
|
platform.async_register_entity_service(
|
||||||
SERVICE_CALIBRATE_METER,
|
SERVICE_CALIBRATE_METER,
|
||||||
{vol.Required(ATTR_VALUE): vol.Coerce(float)},
|
{vol.Required(ATTR_VALUE): vol.Coerce(Decimal)},
|
||||||
"async_calibrate",
|
"async_calibrate",
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -222,7 +222,7 @@ class UtilityMeterSensor(RestoreEntity):
|
|||||||
async def async_calibrate(self, value):
|
async def async_calibrate(self, value):
|
||||||
"""Calibrate the Utility Meter with a given value."""
|
"""Calibrate the Utility Meter with a given value."""
|
||||||
_LOGGER.debug("Calibrate %s = %s", self._name, value)
|
_LOGGER.debug("Calibrate %s = %s", self._name, value)
|
||||||
self._state = Decimal(value)
|
self._state = value
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
|
@ -192,11 +192,7 @@ class UnifiVideoCamera(Camera):
|
|||||||
|
|
||||||
def set_motion_detection(self, mode):
|
def set_motion_detection(self, mode):
|
||||||
"""Set motion detection on or off."""
|
"""Set motion detection on or off."""
|
||||||
|
set_mode = "motion" if mode is True else "none"
|
||||||
if mode is True:
|
|
||||||
set_mode = "motion"
|
|
||||||
else:
|
|
||||||
set_mode = "none"
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._nvr.set_recordmode(self._uuid, set_mode)
|
self._nvr.set_recordmode(self._uuid, set_mode)
|
||||||
@ -215,9 +211,7 @@ class UnifiVideoCamera(Camera):
|
|||||||
|
|
||||||
async def stream_source(self):
|
async def stream_source(self):
|
||||||
"""Return the source of the stream."""
|
"""Return the source of the stream."""
|
||||||
caminfo = self._nvr.get_camera(self._uuid)
|
for channel in self._caminfo["channels"]:
|
||||||
channels = caminfo["channels"]
|
|
||||||
for channel in channels:
|
|
||||||
if channel["isRtspEnabled"]:
|
if channel["isRtspEnabled"]:
|
||||||
return channel["rtspUris"][0]
|
return channel["rtspUris"][0]
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"domain": "websocket_api",
|
"domain": "websocket_api",
|
||||||
"name": "Home Asssitant WebSocket API",
|
"name": "Home Assistant WebSocket API",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/websocket_api",
|
"documentation": "https://www.home-assistant.io/integrations/websocket_api",
|
||||||
"dependencies": ["http"],
|
"dependencies": ["http"],
|
||||||
"codeowners": ["@home-assistant/core"],
|
"codeowners": ["@home-assistant/core"],
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""Constants used by Home Assistant components."""
|
"""Constants used by Home Assistant components."""
|
||||||
MAJOR_VERSION = 0
|
MAJOR_VERSION = 0
|
||||||
MINOR_VERSION = 109
|
MINOR_VERSION = 109
|
||||||
PATCH_VERSION = "3"
|
PATCH_VERSION = "4"
|
||||||
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||||
__version__ = f"{__short_version__}.{PATCH_VERSION}"
|
__version__ = f"{__short_version__}.{PATCH_VERSION}"
|
||||||
REQUIRED_PYTHON_VER = (3, 7, 0)
|
REQUIRED_PYTHON_VER = (3, 7, 0)
|
||||||
|
@ -1342,7 +1342,7 @@ pyhomeworks==0.0.6
|
|||||||
pyialarm==0.3
|
pyialarm==0.3
|
||||||
|
|
||||||
# homeassistant.components.icloud
|
# homeassistant.components.icloud
|
||||||
pyicloud==0.9.6.1
|
pyicloud==0.9.7
|
||||||
|
|
||||||
# homeassistant.components.intesishome
|
# homeassistant.components.intesishome
|
||||||
pyintesishome==1.7.4
|
pyintesishome==1.7.4
|
||||||
@ -1825,7 +1825,7 @@ rocketchat-API==0.6.1
|
|||||||
roku==4.1.0
|
roku==4.1.0
|
||||||
|
|
||||||
# homeassistant.components.roomba
|
# homeassistant.components.roomba
|
||||||
roombapy==1.5.2
|
roombapy==1.5.3
|
||||||
|
|
||||||
# homeassistant.components.rova
|
# homeassistant.components.rova
|
||||||
rova==0.1.0
|
rova==0.1.0
|
||||||
|
@ -537,7 +537,7 @@ pyheos==0.6.0
|
|||||||
pyhomematic==0.1.66
|
pyhomematic==0.1.66
|
||||||
|
|
||||||
# homeassistant.components.icloud
|
# homeassistant.components.icloud
|
||||||
pyicloud==0.9.6.1
|
pyicloud==0.9.7
|
||||||
|
|
||||||
# homeassistant.components.ipma
|
# homeassistant.components.ipma
|
||||||
pyipma==2.0.5
|
pyipma==2.0.5
|
||||||
@ -701,7 +701,7 @@ ring_doorbell==0.6.0
|
|||||||
roku==4.1.0
|
roku==4.1.0
|
||||||
|
|
||||||
# homeassistant.components.roomba
|
# homeassistant.components.roomba
|
||||||
roombapy==1.5.2
|
roombapy==1.5.3
|
||||||
|
|
||||||
# homeassistant.components.yamaha
|
# homeassistant.components.yamaha
|
||||||
rxv==0.6.0
|
rxv==0.6.0
|
||||||
|
@ -5,7 +5,6 @@ from roomba import RoombaConnectionError
|
|||||||
from homeassistant import config_entries, data_entry_flow, setup
|
from homeassistant import config_entries, data_entry_flow, setup
|
||||||
from homeassistant.components.roomba.const import (
|
from homeassistant.components.roomba.const import (
|
||||||
CONF_BLID,
|
CONF_BLID,
|
||||||
CONF_CERT,
|
|
||||||
CONF_CONTINUOUS,
|
CONF_CONTINUOUS,
|
||||||
CONF_DELAY,
|
CONF_DELAY,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
@ -20,7 +19,6 @@ VALID_YAML_CONFIG = {
|
|||||||
CONF_HOST: "1.2.3.4",
|
CONF_HOST: "1.2.3.4",
|
||||||
CONF_BLID: "blid",
|
CONF_BLID: "blid",
|
||||||
CONF_PASSWORD: "password",
|
CONF_PASSWORD: "password",
|
||||||
CONF_CERT: "/etc/ssl/certs/ca-certificates.crt",
|
|
||||||
CONF_CONTINUOUS: True,
|
CONF_CONTINUOUS: True,
|
||||||
CONF_DELAY: 1,
|
CONF_DELAY: 1,
|
||||||
}
|
}
|
||||||
@ -69,7 +67,6 @@ async def test_form(hass):
|
|||||||
assert result2["result"].unique_id == "blid"
|
assert result2["result"].unique_id == "blid"
|
||||||
assert result2["data"] == {
|
assert result2["data"] == {
|
||||||
CONF_BLID: "blid",
|
CONF_BLID: "blid",
|
||||||
CONF_CERT: "/etc/ssl/certs/ca-certificates.crt",
|
|
||||||
CONF_CONTINUOUS: True,
|
CONF_CONTINUOUS: True,
|
||||||
CONF_DELAY: 1,
|
CONF_DELAY: 1,
|
||||||
CONF_HOST: "1.2.3.4",
|
CONF_HOST: "1.2.3.4",
|
||||||
@ -131,7 +128,6 @@ async def test_form_import(hass):
|
|||||||
assert result["title"] == "imported_roomba"
|
assert result["title"] == "imported_roomba"
|
||||||
assert result["data"] == {
|
assert result["data"] == {
|
||||||
CONF_BLID: "blid",
|
CONF_BLID: "blid",
|
||||||
CONF_CERT: "/etc/ssl/certs/ca-certificates.crt",
|
|
||||||
CONF_CONTINUOUS: True,
|
CONF_CONTINUOUS: True,
|
||||||
CONF_DELAY: 1,
|
CONF_DELAY: 1,
|
||||||
CONF_HOST: "1.2.3.4",
|
CONF_HOST: "1.2.3.4",
|
||||||
|
@ -25,6 +25,7 @@ from homeassistant.config_entries import SOURCE_IMPORT, SOURCE_SSDP, SOURCE_USER
|
|||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_DISKS,
|
CONF_DISKS,
|
||||||
CONF_HOST,
|
CONF_HOST,
|
||||||
|
CONF_MAC,
|
||||||
CONF_PASSWORD,
|
CONF_PASSWORD,
|
||||||
CONF_PORT,
|
CONF_PORT,
|
||||||
CONF_SSL,
|
CONF_SSL,
|
||||||
@ -47,6 +48,8 @@ USERNAME = "Home_Assistant"
|
|||||||
PASSWORD = "password"
|
PASSWORD = "password"
|
||||||
DEVICE_TOKEN = "Dév!cè_T0k€ñ"
|
DEVICE_TOKEN = "Dév!cè_T0k€ñ"
|
||||||
|
|
||||||
|
MACS = ["00-11-32-XX-XX-59", "00-11-32-XX-XX-5A"]
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(name="service")
|
@pytest.fixture(name="service")
|
||||||
def mock_controller_service():
|
def mock_controller_service():
|
||||||
@ -56,8 +59,9 @@ def mock_controller_service():
|
|||||||
) as service_mock:
|
) as service_mock:
|
||||||
service_mock.return_value.information.serial = SERIAL
|
service_mock.return_value.information.serial = SERIAL
|
||||||
service_mock.return_value.utilisation.cpu_user_load = 1
|
service_mock.return_value.utilisation.cpu_user_load = 1
|
||||||
service_mock.return_value.storage.disks_ids = []
|
service_mock.return_value.storage.disks_ids = ["sda", "sdb", "sdc"]
|
||||||
service_mock.return_value.storage.volumes_ids = []
|
service_mock.return_value.storage.volumes_ids = ["volume_1"]
|
||||||
|
service_mock.return_value.network.macs = MACS
|
||||||
yield service_mock
|
yield service_mock
|
||||||
|
|
||||||
|
|
||||||
@ -72,8 +76,9 @@ def mock_controller_service_2sa():
|
|||||||
)
|
)
|
||||||
service_mock.return_value.information.serial = SERIAL
|
service_mock.return_value.information.serial = SERIAL
|
||||||
service_mock.return_value.utilisation.cpu_user_load = 1
|
service_mock.return_value.utilisation.cpu_user_load = 1
|
||||||
service_mock.return_value.storage.disks_ids = []
|
service_mock.return_value.storage.disks_ids = ["sda", "sdb", "sdc"]
|
||||||
service_mock.return_value.storage.volumes_ids = []
|
service_mock.return_value.storage.volumes_ids = ["volume_1"]
|
||||||
|
service_mock.return_value.network.macs = MACS
|
||||||
yield service_mock
|
yield service_mock
|
||||||
|
|
||||||
|
|
||||||
@ -85,8 +90,9 @@ def mock_controller_service_failed():
|
|||||||
) as service_mock:
|
) as service_mock:
|
||||||
service_mock.return_value.information.serial = None
|
service_mock.return_value.information.serial = None
|
||||||
service_mock.return_value.utilisation.cpu_user_load = None
|
service_mock.return_value.utilisation.cpu_user_load = None
|
||||||
service_mock.return_value.storage.disks_ids = None
|
service_mock.return_value.storage.disks_ids = []
|
||||||
service_mock.return_value.storage.volumes_ids = None
|
service_mock.return_value.storage.volumes_ids = []
|
||||||
|
service_mock.return_value.network.macs = []
|
||||||
yield service_mock
|
yield service_mock
|
||||||
|
|
||||||
|
|
||||||
@ -118,6 +124,7 @@ async def test_user(hass: HomeAssistantType, service: MagicMock):
|
|||||||
assert result["data"][CONF_SSL] == SSL
|
assert result["data"][CONF_SSL] == SSL
|
||||||
assert result["data"][CONF_USERNAME] == USERNAME
|
assert result["data"][CONF_USERNAME] == USERNAME
|
||||||
assert result["data"][CONF_PASSWORD] == PASSWORD
|
assert result["data"][CONF_PASSWORD] == PASSWORD
|
||||||
|
assert result["data"][CONF_MAC] == MACS
|
||||||
assert result["data"].get("device_token") is None
|
assert result["data"].get("device_token") is None
|
||||||
assert result["data"].get(CONF_DISKS) is None
|
assert result["data"].get(CONF_DISKS) is None
|
||||||
assert result["data"].get(CONF_VOLUMES) is None
|
assert result["data"].get(CONF_VOLUMES) is None
|
||||||
@ -142,6 +149,7 @@ async def test_user(hass: HomeAssistantType, service: MagicMock):
|
|||||||
assert not result["data"][CONF_SSL]
|
assert not result["data"][CONF_SSL]
|
||||||
assert result["data"][CONF_USERNAME] == USERNAME
|
assert result["data"][CONF_USERNAME] == USERNAME
|
||||||
assert result["data"][CONF_PASSWORD] == PASSWORD
|
assert result["data"][CONF_PASSWORD] == PASSWORD
|
||||||
|
assert result["data"][CONF_MAC] == MACS
|
||||||
assert result["data"].get("device_token") is None
|
assert result["data"].get("device_token") is None
|
||||||
assert result["data"].get(CONF_DISKS) is None
|
assert result["data"].get(CONF_DISKS) is None
|
||||||
assert result["data"].get(CONF_VOLUMES) is None
|
assert result["data"].get(CONF_VOLUMES) is None
|
||||||
@ -183,6 +191,7 @@ async def test_user_2sa(hass: HomeAssistantType, service_2sa: MagicMock):
|
|||||||
assert result["data"][CONF_SSL] == DEFAULT_SSL
|
assert result["data"][CONF_SSL] == DEFAULT_SSL
|
||||||
assert result["data"][CONF_USERNAME] == USERNAME
|
assert result["data"][CONF_USERNAME] == USERNAME
|
||||||
assert result["data"][CONF_PASSWORD] == PASSWORD
|
assert result["data"][CONF_PASSWORD] == PASSWORD
|
||||||
|
assert result["data"][CONF_MAC] == MACS
|
||||||
assert result["data"].get("device_token") == DEVICE_TOKEN
|
assert result["data"].get("device_token") == DEVICE_TOKEN
|
||||||
assert result["data"].get(CONF_DISKS) is None
|
assert result["data"].get(CONF_DISKS) is None
|
||||||
assert result["data"].get(CONF_VOLUMES) is None
|
assert result["data"].get(CONF_VOLUMES) is None
|
||||||
@ -204,6 +213,7 @@ async def test_import(hass: HomeAssistantType, service: MagicMock):
|
|||||||
assert result["data"][CONF_SSL] == DEFAULT_SSL
|
assert result["data"][CONF_SSL] == DEFAULT_SSL
|
||||||
assert result["data"][CONF_USERNAME] == USERNAME
|
assert result["data"][CONF_USERNAME] == USERNAME
|
||||||
assert result["data"][CONF_PASSWORD] == PASSWORD
|
assert result["data"][CONF_PASSWORD] == PASSWORD
|
||||||
|
assert result["data"][CONF_MAC] == MACS
|
||||||
assert result["data"].get("device_token") is None
|
assert result["data"].get("device_token") is None
|
||||||
assert result["data"].get(CONF_DISKS) is None
|
assert result["data"].get(CONF_DISKS) is None
|
||||||
assert result["data"].get(CONF_VOLUMES) is None
|
assert result["data"].get(CONF_VOLUMES) is None
|
||||||
@ -231,6 +241,7 @@ async def test_import(hass: HomeAssistantType, service: MagicMock):
|
|||||||
assert result["data"][CONF_SSL] == SSL
|
assert result["data"][CONF_SSL] == SSL
|
||||||
assert result["data"][CONF_USERNAME] == USERNAME
|
assert result["data"][CONF_USERNAME] == USERNAME
|
||||||
assert result["data"][CONF_PASSWORD] == PASSWORD
|
assert result["data"][CONF_PASSWORD] == PASSWORD
|
||||||
|
assert result["data"][CONF_MAC] == MACS
|
||||||
assert result["data"].get("device_token") is None
|
assert result["data"].get("device_token") is None
|
||||||
assert result["data"][CONF_DISKS] == ["sda", "sdb", "sdc"]
|
assert result["data"][CONF_DISKS] == ["sda", "sdb", "sdc"]
|
||||||
assert result["data"][CONF_VOLUMES] == ["volume_1"]
|
assert result["data"][CONF_VOLUMES] == ["volume_1"]
|
||||||
@ -329,8 +340,13 @@ async def test_form_ssdp_already_configured(
|
|||||||
|
|
||||||
MockConfigEntry(
|
MockConfigEntry(
|
||||||
domain=DOMAIN,
|
domain=DOMAIN,
|
||||||
data={CONF_HOST: HOST, CONF_USERNAME: USERNAME, CONF_PASSWORD: PASSWORD},
|
data={
|
||||||
unique_id=SERIAL.upper(),
|
CONF_HOST: HOST,
|
||||||
|
CONF_USERNAME: USERNAME,
|
||||||
|
CONF_PASSWORD: PASSWORD,
|
||||||
|
CONF_MAC: MACS,
|
||||||
|
},
|
||||||
|
unique_id=SERIAL,
|
||||||
).add_to_hass(hass)
|
).add_to_hass(hass)
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
@ -339,7 +355,7 @@ async def test_form_ssdp_already_configured(
|
|||||||
data={
|
data={
|
||||||
ssdp.ATTR_SSDP_LOCATION: "http://192.168.1.5:5000",
|
ssdp.ATTR_SSDP_LOCATION: "http://192.168.1.5:5000",
|
||||||
ssdp.ATTR_UPNP_FRIENDLY_NAME: "mydsm",
|
ssdp.ATTR_UPNP_FRIENDLY_NAME: "mydsm",
|
||||||
ssdp.ATTR_UPNP_SERIAL: SERIAL,
|
ssdp.ATTR_UPNP_SERIAL: "001132XXXX59", # Existing in MACS[0], but SSDP does not have `-`
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||||
@ -355,7 +371,7 @@ async def test_form_ssdp(hass: HomeAssistantType, service: MagicMock):
|
|||||||
data={
|
data={
|
||||||
ssdp.ATTR_SSDP_LOCATION: "http://192.168.1.5:5000",
|
ssdp.ATTR_SSDP_LOCATION: "http://192.168.1.5:5000",
|
||||||
ssdp.ATTR_UPNP_FRIENDLY_NAME: "mydsm",
|
ssdp.ATTR_UPNP_FRIENDLY_NAME: "mydsm",
|
||||||
ssdp.ATTR_UPNP_SERIAL: SERIAL,
|
ssdp.ATTR_UPNP_SERIAL: "001132XXXX99", # MAC address, but SSDP does not have `-`
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
@ -373,6 +389,7 @@ async def test_form_ssdp(hass: HomeAssistantType, service: MagicMock):
|
|||||||
assert result["data"][CONF_SSL] == DEFAULT_SSL
|
assert result["data"][CONF_SSL] == DEFAULT_SSL
|
||||||
assert result["data"][CONF_USERNAME] == USERNAME
|
assert result["data"][CONF_USERNAME] == USERNAME
|
||||||
assert result["data"][CONF_PASSWORD] == PASSWORD
|
assert result["data"][CONF_PASSWORD] == PASSWORD
|
||||||
|
assert result["data"][CONF_MAC] == MACS
|
||||||
assert result["data"].get("device_token") is None
|
assert result["data"].get("device_token") is None
|
||||||
assert result["data"].get(CONF_DISKS) is None
|
assert result["data"].get(CONF_DISKS) is None
|
||||||
assert result["data"].get(CONF_VOLUMES) is None
|
assert result["data"].get(CONF_VOLUMES) is None
|
||||||
|
@ -119,6 +119,17 @@ async def test_state(hass):
|
|||||||
assert state is not None
|
assert state is not None
|
||||||
assert state.state == "100"
|
assert state.state == "100"
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_CALIBRATE_METER,
|
||||||
|
{ATTR_ENTITY_ID: "sensor.energy_bill_midpeak", ATTR_VALUE: "0.123"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get("sensor.energy_bill_midpeak")
|
||||||
|
assert state is not None
|
||||||
|
assert state.state == "0.123"
|
||||||
|
|
||||||
|
|
||||||
async def test_net_consumption(hass):
|
async def test_net_consumption(hass):
|
||||||
"""Test utility sensor state."""
|
"""Test utility sensor state."""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user