Merge pull request #35221 from home-assistant/rc

This commit is contained in:
Paulus Schoutsen 2020-05-04 20:06:57 -07:00 committed by GitHub
commit d2179e5321
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 91 additions and 68 deletions

View File

@ -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)

View File

@ -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 = []

View File

@ -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

View File

@ -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:

View File

@ -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"]
} }

View File

@ -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],
) )

View File

@ -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],
) )

View File

@ -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"]
} }

View File

@ -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"
} }

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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):

View File

@ -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]

View File

@ -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"],

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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",

View File

@ -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

View File

@ -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."""