diff --git a/custom_components/victron/__init__.py b/custom_components/victron/__init__.py index 9672a6c..1103a1b 100644 --- a/custom_components/victron/__init__.py +++ b/custom_components/victron/__init__.py @@ -1,4 +1,4 @@ -"""The victron integration.""" +"""The Victron GX modbusTCP integration.""" from __future__ import annotations @@ -7,47 +7,33 @@ from homeassistant.core import HomeAssistant from .const import CONF_HOST, CONF_INTERVAL, CONF_PORT, DOMAIN, SCAN_REGISTERS -from .coordinator import victronEnergyDeviceUpdateCoordinator as Coordinator - -PLATFORMS: list[Platform] = [ - Platform.SENSOR, - Platform.SWITCH, - Platform.NUMBER, - Platform.SELECT, - Platform.BINARY_SENSOR, - Platform.BUTTON, -] +from .coordinator import VictronEnergyDeviceUpdateCoordinator as Coordinator +# For your initial PR, limit it to 1 platform. +# There will be also: SWITCH, NUMBER, SELECT, BINARY_SENSOR, BUTTON +_PLATFORMS: list[Platform] = [Platform.SENSOR] async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: """Set up victron from a config entry.""" hass.data.setdefault(DOMAIN, {}) - # TODO 1. Create API instance - # TODO 2. Validate the API connection (and authentication) - # TODO 3. Store an API object for your platforms to access - # hass.data[DOMAIN][entry.entry_id] = MyApi(...) - coordinator = Coordinator( + coordinator_ = Coordinator( hass, config_entry.options[CONF_HOST], config_entry.options[CONF_PORT], config_entry.data[SCAN_REGISTERS], config_entry.options[CONF_INTERVAL], ) - # try: - # await coordinator.async_config_entry_first_refresh() - # except ConfigEntryNotReady: - # await coordinator.api.close() - # raise # Finalize hass.data.setdefault(DOMAIN, {}) - hass.data[DOMAIN][config_entry.entry_id] = coordinator + hass.data[DOMAIN][config_entry.entry_id] = coordinator_ - await coordinator.async_config_entry_first_refresh() + await coordinator_.async_config_entry_first_refresh() config_entry.async_on_unload(config_entry.add_update_listener(update_listener)) - await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS) + config_entry.runtime_data = coordinator_ + await hass.config_entries.async_forward_entry_setups(config_entry, _PLATFORMS) return True @@ -55,7 +41,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: """Unload a config entry.""" if unload_ok := await hass.config_entries.async_unload_platforms( - config_entry, PLATFORMS + config_entry, _PLATFORMS ): hass.data[DOMAIN].pop(config_entry.entry_id) diff --git a/custom_components/victron/binary_sensor.py b/custom_components/victron/binary_sensor.py index 75e70c4..169e566 100644 --- a/custom_components/victron/binary_sensor.py +++ b/custom_components/victron/binary_sensor.py @@ -2,9 +2,10 @@ from __future__ import annotations +from collections import OrderedDict from dataclasses import dataclass import logging -from typing import cast +from typing import Any, cast from homeassistant.components.binary_sensor import ( DOMAIN as BINARY_SENSOR_DOMAIN, @@ -13,13 +14,14 @@ ) from homeassistant.config_entries import ConfigEntry from homeassistant.core import HassJob, HomeAssistant -from homeassistant.helpers import entity +from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity -from .base import VictronBaseEntityDescription from .const import DOMAIN, BoolReadEntityType, register_info_dict -from .coordinator import victronEnergyDeviceUpdateCoordinator +from .coordinator import VictronEnergyDeviceUpdateCoordinator +from .entity import VictronBaseEntityDescription +from .select import VictronSelect _LOGGER = logging.getLogger(__name__) @@ -31,44 +33,46 @@ async def async_setup_entry( ) -> None: """Set up Victron energy binary sensor entries.""" _LOGGER.debug("attempting to setup binary sensor entities") - victron_coordinator: victronEnergyDeviceUpdateCoordinator = hass.data[DOMAIN][ + victron_coordinator: VictronEnergyDeviceUpdateCoordinator = hass.data[DOMAIN][ config_entry.entry_id ] _LOGGER.debug(victron_coordinator.processed_data()["register_set"]) _LOGGER.debug(victron_coordinator.processed_data()["data"]) descriptions = [] # TODO cleanup - register_set = victron_coordinator.processed_data()["register_set"] + register_set: dict[str, OrderedDict] = victron_coordinator.processed_data()[ + "register_set" + ] for slave, registerLedger in register_set.items(): for name in registerLedger: for register_name, registerInfo in register_info_dict[name].items(): _LOGGER.debug( - "unit == %s registerLedger == %s registerInfo", + "unit == %s registerLedger == %s register_info", slave, registerLedger, ) - if isinstance(registerInfo.entityType, BoolReadEntityType): + if isinstance(registerInfo.entity_type, BoolReadEntityType): description = VictronEntityDescription( key=register_name, name=register_name.replace("_", " "), - slave=slave, + slave=slave, # type: ignore[arg-type] ) _LOGGER.debug("composed description == %s", description) descriptions.append(description) - entities = [] - entity = {} - for description in descriptions: - entity = description - entities.append(VictronBinarySensor(victron_coordinator, entity)) + _entities = [ + VictronSelect(hass, victron_coordinator, description) + for description in descriptions + ] - async_add_entities(entities, True) + async_add_entities(_entities, True) -@dataclass +@dataclass(frozen=True) class VictronEntityDescription( - BinarySensorEntityDescription, VictronBaseEntityDescription + BinarySensorEntityDescription, + VictronBaseEntityDescription, ): """Describes victron sensor entity.""" @@ -78,7 +82,7 @@ class VictronBinarySensor(CoordinatorEntity, BinarySensorEntity): def __init__( self, - coordinator: victronEnergyDeviceUpdateCoordinator, + coordinator: VictronEnergyDeviceUpdateCoordinator, description: VictronEntityDescription, ) -> None: """Initialize the binary sensor.""" @@ -101,7 +105,7 @@ def __init__( @property def is_on(self) -> bool: """Return True if the binary sensor is on.""" - data = self.description.value_fn( + data = self.description.value_fn( # type: ignore[call-arg] self.coordinator.processed_data(), self.description.slave, self.description.key, @@ -109,17 +113,17 @@ def is_on(self) -> bool: return cast("bool", data) @property - def available(self) -> bool: + def available(self) -> Any: """Return True if entity is available.""" full_key = str(self.description.slave) + "." + self.description.key return self.coordinator.processed_data()["availability"][full_key] @property - def device_info(self) -> entity.DeviceInfo: + def device_info(self) -> DeviceInfo: """Return the device info.""" - return entity.DeviceInfo( - identifiers={(DOMAIN, self.unique_id.split("_")[0])}, - name=self.unique_id.split("_")[1], - model=self.unique_id.split("_")[0], + return DeviceInfo( + identifiers={(DOMAIN, self.unique_id.split("_", maxsplit=1)[0])}, + name=self.unique_id.split("_", maxsplit=1)[1], + model=self.unique_id.split("_", maxsplit=1)[0], manufacturer="victron", ) diff --git a/custom_components/victron/button.py b/custom_components/victron/button.py index 84d71fc..d293607 100644 --- a/custom_components/victron/button.py +++ b/custom_components/victron/button.py @@ -4,6 +4,7 @@ from dataclasses import dataclass import logging +from typing import Any from homeassistant.components.button import ( DOMAIN as BUTTON_DOMAIN, @@ -13,13 +14,14 @@ ) from homeassistant.config_entries import ConfigEntry from homeassistant.core import HassJob, HomeAssistant -from homeassistant.helpers import entity +from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity -from .base import VictronWriteBaseEntityDescription from .const import CONF_ADVANCED_OPTIONS, DOMAIN, ButtonWriteType, register_info_dict -from .coordinator import victronEnergyDeviceUpdateCoordinator +from .coordinator import VictronEnergyDeviceUpdateCoordinator +from .entity import VictronWriteBaseEntityDescription +from .select import VictronSelect _LOGGER = logging.getLogger(__name__) @@ -31,24 +33,24 @@ async def async_setup_entry( ) -> None: """Set up Victron energy binary sensor entries.""" _LOGGER.debug("attempting to setup button entities") - victron_coordinator: victronEnergyDeviceUpdateCoordinator = hass.data[DOMAIN][ + victron_coordinator: VictronEnergyDeviceUpdateCoordinator = hass.data[DOMAIN][ config_entry.entry_id ] descriptions = [] # TODO cleanup - register_set = victron_coordinator.processed_data()["register_set"] + register_set: Any = victron_coordinator.processed_data()["register_set"] for slave, registerLedger in register_set.items(): for name in registerLedger: for register_name, registerInfo in register_info_dict[name].items(): _LOGGER.debug( - "unit == %s registerLedger == %s registerInfo", + "unit == %s registerLedger == %s register_info", slave, registerLedger, ) if not config_entry.options[CONF_ADVANCED_OPTIONS]: continue - if isinstance(registerInfo.entityType, ButtonWriteType): + if isinstance(registerInfo.entity_type, ButtonWriteType): description = VictronEntityDescription( key=register_name, name=register_name.replace("_", " "), @@ -59,18 +61,18 @@ async def async_setup_entry( _LOGGER.debug("composed description == %s", description) descriptions.append(description) - entities = [] - entity = {} - for description in descriptions: - entity = description - entities.append(VictronBinarySensor(victron_coordinator, entity)) + _entities = [ + VictronSelect(hass, victron_coordinator, description) + for description in descriptions + ] - async_add_entities(entities, True) + async_add_entities(_entities, True) -@dataclass +@dataclass(frozen=True) class VictronEntityDescription( - ButtonEntityDescription, VictronWriteBaseEntityDescription + ButtonEntityDescription, + VictronWriteBaseEntityDescription, ): """Describes victron sensor entity.""" @@ -80,7 +82,7 @@ class VictronBinarySensor(CoordinatorEntity, ButtonEntity): def __init__( self, - coordinator: victronEnergyDeviceUpdateCoordinator, + coordinator: VictronEnergyDeviceUpdateCoordinator, description: VictronEntityDescription, ) -> None: """Initialize the sensor.""" @@ -106,17 +108,17 @@ async def async_press(self) -> None: ) @property - def available(self) -> bool: + def available(self) -> Any: """Return True if entity available.""" full_key = str(self.description.slave) + "." + self.description.key return self.coordinator.processed_data()["availability"][full_key] @property - def device_info(self) -> entity.DeviceInfo: + def device_info(self) -> DeviceInfo: """Return the device info.""" - return entity.DeviceInfo( - identifiers={(DOMAIN, self.unique_id.split("_")[0])}, - name=self.unique_id.split("_")[1], - model=self.unique_id.split("_")[0], + return DeviceInfo( + identifiers={(DOMAIN, self.unique_id.split("_", maxsplit=1)[0])}, + name=self.unique_id.split("_", maxsplit=1)[1], + model=self.unique_id.split("_", maxsplit=1)[0], manufacturer="victron", ) diff --git a/custom_components/victron/config_flow.py b/custom_components/victron/config_flow.py index 0eabab3..a813a37 100644 --- a/custom_components/victron/config_flow.py +++ b/custom_components/victron/config_flow.py @@ -1,14 +1,24 @@ -"""Config flow for victron integration.""" +"""Config flow for the Victron GX modbusTCP integration.""" from __future__ import annotations +from collections import OrderedDict import logging +import threading from typing import Any +from packaging import version +import pymodbus +from pymodbus.client import ModbusTcpClient import voluptuous as vol -from homeassistant import config_entries -from homeassistant.config_entries import ConfigEntry +from homeassistant.config_entries import ( + ConfigEntry, + ConfigFlow, + ConfigFlowResult, + OptionsFlow, +) +from homeassistant.const import CONF_HOST, CONF_PORT from homeassistant.core import HomeAssistant, callback from homeassistant.data_entry_flow import FlowResult from homeassistant.exceptions import HomeAssistantError @@ -25,18 +35,22 @@ CONF_ADVANCED_OPTIONS, CONF_DC_CURRENT_LIMIT, CONF_DC_SYSTEM_VOLTAGE, - CONF_HOST, CONF_INTERVAL, CONF_NUMBER_OF_PHASES, - CONF_PORT, CONF_USE_SLIDERS, DC_VOLTAGES, DOMAIN, + INT16, + INT32, PHASE_CONFIGURATIONS, SCAN_REGISTERS, + STRING, + UINT16, + UINT32, RegisterInfo, + register_info_dict, + valid_unit_ids, ) -from .hub import VictronHub _LOGGER = logging.getLogger(__name__) @@ -51,27 +65,193 @@ } ) +STEP_USER_DATA_ADVANCED_SCHEMA = vol.Schema( + { + vol.Required( + CONF_AC_SYSTEM_VOLTAGE, default=str(AC_VOLTAGES["US (120)"]) + ): SelectSelector( + SelectSelectorConfig( + options=[ + SelectOptionDict(value=str(value), label=key) + for key, value in AC_VOLTAGES.items() + ] + ), + ), + vol.Required( + CONF_NUMBER_OF_PHASES, + default=str(PHASE_CONFIGURATIONS["single phase"]), + ): SelectSelector( + SelectSelectorConfig( + options=[ + SelectOptionDict(value=str(value), label=key) + for key, value in PHASE_CONFIGURATIONS.items() + ] + ), + ), + vol.Required(CONF_AC_CURRENT_LIMIT, default=0): vol.All( + vol.Coerce(int, "must be a number") + ), + vol.Required( + CONF_DC_SYSTEM_VOLTAGE, default=str(DC_VOLTAGES["lifepo4_12v"]) + ): SelectSelector( + SelectSelectorConfig( + options=[ + SelectOptionDict(value=str(value), label=key) + for key, value in DC_VOLTAGES.items() + ] + ), + ), + vol.Required(CONF_DC_CURRENT_LIMIT, default=0): vol.All( + vol.Coerce(int, "must be a number") + ), + vol.Optional(CONF_USE_SLIDERS, default=True): bool, + } +) + + +class VictronHub: + """Victron Hub.""" + + def __init__(self, host: str, port: int) -> None: + """Initialize.""" + self.host = host + self.port = port + self._client = ModbusTcpClient(host=self.host, port=self.port) + self._lock = threading.Lock() + + def is_still_connected(self) -> Any: + """Check if the connection is still open.""" + return self._client.is_socket_open() + + def convert_string_from_register( + self, segment: list[int], string_encoding: str = "ascii" + ) -> Any: + """Convert from registers to the appropriate data type.""" + if ( + version.parse("3.8.0") + <= version.parse(pymodbus.__version__) + <= version.parse("3.8.4") + ): + return self._client.convert_from_registers( + segment, self._client.DATATYPE.STRING + ).split("\x00")[0] + return self._client.convert_from_registers( + segment, self._client.DATATYPE.STRING, string_encoding=string_encoding + ).split("\x00")[0] + + def convert_number_from_register(self, segment: list[int], data_type: Any) -> Any: + """Convert from registers to the appropriate data type.""" + raw: Any | None = None + if data_type == UINT16: + raw = self._client.convert_from_registers( + segment, data_type=self._client.DATATYPE.UINT16 + ) + elif data_type == INT16: + raw = self._client.convert_from_registers( + segment, data_type=self._client.DATATYPE.INT16 + ) + elif data_type == UINT32: + raw = self._client.convert_from_registers( + segment, data_type=self._client.DATATYPE.UINT32 + ) + elif data_type == INT32: + raw = self._client.convert_from_registers( + segment, data_type=self._client.DATATYPE.INT32 + ) + return raw + + def connect(self) -> Any: + """Connect to the Modbus TCP server.""" + if self._client.is_socket_open(): + return True + return self._client.connect() + + def disconnect(self) -> Any: + """Disconnect from the Modbus TCP server.""" + if self._client.is_socket_open(): + return self._client.close() + return None + + def write_register(self, unit: Any, address: int, value: int) -> Any: + """Write a register.""" + return self._client.write_register(address=address, value=value) + + def read_holding_registers(self, unit: Any, address: int, count: int) -> Any: + """Read holding registers.""" + return self._client.read_holding_registers( + address=address, count=count + ) + + @staticmethod + def calculate_register_count(register_info_dict_: OrderedDict | dict) -> Any: + """Calculate the number of registers to read.""" + first_key = next(iter(register_info_dict_)) + last_key = next(reversed(register_info_dict_)) + end_correction = 1 + if register_info_dict_[last_key].data_type in (INT32, UINT32): + end_correction = 2 + elif isinstance(register_info_dict_[last_key].data_type, STRING): + end_correction = register_info_dict_[last_key].data_type.length + + return ( + register_info_dict_[last_key].register + - register_info_dict_[first_key].register + ) + end_correction + + @staticmethod + def get_first_register_id(register_info_dict_: OrderedDict | dict) -> Any: + """Return first register id.""" + first_register = next(iter(register_info_dict_)) + return register_info_dict_[first_register].register + + def determine_present_devices(self) -> Any: + """Determine which devices are present.""" + valid_devices = {} + + for unit in valid_unit_ids: + working_registers = [] + for key, register_definition in register_info_dict.items(): + # VE.CAN device zero is present under unit 100. This seperates non system / settings entities into the seperate can device + if unit == 100 and not key.startswith(("settings", "system")): + continue + + try: + address = self.get_first_register_id(register_definition) + count = self.calculate_register_count(register_definition) + result = self.read_holding_registers(unit, address, count) + if result.isError(): + _LOGGER.debug( + "result is error for unit: %s address: %s count: %s", + unit, + address, + count, + ) + else: + working_registers.append(key) + except HomeAssistantError as e: + _LOGGER.error(e) + + if len(working_registers) > 0: + valid_devices[unit] = working_registers + else: + _LOGGER.debug("no registers found for unit: %s", unit) + + return valid_devices + async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> dict[str, Any]: """Validate the user input allows us to connect. Data has the keys from STEP_USER_DATA_SCHEMA with values provided by the user. """ - # TODO validate the data can be used to set up a connection. - - # If your PyPI package is not built with async, pass your methods - # to the executor: - # await hass.async_add_executor_job( - # your_validate_func, data["username"], data["password"] - # ) - + discovered_devices: Any | None = None _LOGGER.debug("host = %s", data[CONF_HOST]) _LOGGER.debug("port = %s", data[CONF_PORT]) hub = VictronHub(data[CONF_HOST], data[CONF_PORT]) try: hub.connect() - _LOGGER.debug("connection was succesfull") + _LOGGER.debug("connection was successful") discovered_devices = await scan_connected_devices(hub=hub) _LOGGER.debug("successfully discovered devices") except HomeAssistantError: @@ -79,23 +259,23 @@ async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> dict[str, return {"title": DOMAIN, "data": discovered_devices} -async def scan_connected_devices(hub: VictronHub) -> list: +async def scan_connected_devices(hub: VictronHub) -> Any: """Scan for connected devices.""" return hub.determine_present_devices() -class VictronFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): +class VictronFlowHandler(ConfigFlow, domain=DOMAIN): """Handle a config flow for victron.""" _LOGGER = logging.getLogger(__name__) VERSION = 1 - def __init__(self): + def __init__(self) -> None: """Initialize the config flow.""" - self.advanced_options = None - self.interval = None - self.port = None - self.host = None + self.advanced_options: bool | None = None + self.interval: int | None = None + self.port: int | None = None + self.host: str | None = None @staticmethod @callback @@ -105,9 +285,7 @@ def async_get_options_flow( """Get the options flow for this handler.""" return VictronOptionFlowHandler(config_entry) - async def async_step_user( - self, user_input: dict[str, Any] | None = None - ) -> FlowResult: + async def async_step_user(self, user_input: dict[str, Any] | None = None) -> Any: """Handle the initial step.""" if user_input is None: return self.async_show_form( @@ -119,7 +297,7 @@ async def async_step_user( self.port = user_input[CONF_PORT] self.interval = user_input[CONF_INTERVAL] self.advanced_options = user_input[CONF_ADVANCED_OPTIONS] - return await self.async_step_advanced() + return await self.async_step_advanced(user_input) errors = {} already_configured = False @@ -134,6 +312,7 @@ async def async_step_user( errors["base"] = f"already_configured: {e!s}" already_configured = True + info: dict = {} if not already_configured: try: info = await validate_input(self.hass, user_input) @@ -146,101 +325,59 @@ async def async_step_user( errors["base"] = "unknown" # data property can't be changed in options flow if user wants to refresh - options = user_input - return self.async_create_entry( - title=info["title"], - data={SCAN_REGISTERS: info["data"]}, - options=options, - ) + else: + options = user_input + return self.async_create_entry( + title=info["title"], + data={SCAN_REGISTERS: info["data"]}, + options=options, + ) return self.async_show_form( step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors ) - async def async_step_advanced(self, user_input=None): + async def async_step_advanced(self, user_input: Any) -> ConfigFlowResult: """Handle write support and limit settings if requested.""" - errors = {} + errors: dict = {} + info: dict = {} if user_input is not None: - if self.host is not None: - options = user_input - options[CONF_HOST] = self.host - options[CONF_PORT] = self.port - options[CONF_INTERVAL] = self.interval - options[CONF_ADVANCED_OPTIONS] = bool(self.advanced_options) - options[CONF_NUMBER_OF_PHASES] = int(user_input[CONF_NUMBER_OF_PHASES]) - options[CONF_USE_SLIDERS] = bool(user_input[CONF_USE_SLIDERS]) - options[CONF_AC_SYSTEM_VOLTAGE] = int( - user_input[CONF_AC_SYSTEM_VOLTAGE] - ) - options[CONF_DC_SYSTEM_VOLTAGE] = int( - user_input[CONF_DC_SYSTEM_VOLTAGE] - ) + options = user_input + options[CONF_HOST] = self.host + options[CONF_PORT] = self.port + options[CONF_INTERVAL] = self.interval + options[CONF_ADVANCED_OPTIONS] = bool(self.advanced_options) + options[CONF_NUMBER_OF_PHASES] = int(user_input[CONF_NUMBER_OF_PHASES]) + options[CONF_USE_SLIDERS] = bool(user_input[CONF_USE_SLIDERS]) + options[CONF_AC_SYSTEM_VOLTAGE] = int(user_input[CONF_AC_SYSTEM_VOLTAGE]) + options[CONF_DC_SYSTEM_VOLTAGE] = int(user_input[CONF_DC_SYSTEM_VOLTAGE]) - try: - info = await validate_input(self.hass, user_input) - except CannotConnect: - errors["base"] = "cannot_connect" - except InvalidAuth: - errors["base"] = "invalid_auth" - except HomeAssistantError: - _LOGGER.exception("Unexpected exception") - errors["base"] = "unknown" - _LOGGER.debug("setting up extra entry") - return self.async_create_entry( - title=info["title"], - data={SCAN_REGISTERS: info["data"]}, - options=options, - ) + try: + info = await validate_input(self.hass, options) + except CannotConnect: + errors["base"] = "cannot_connect" + except InvalidAuth: + errors["base"] = "invalid_auth" + except HomeAssistantError: + _LOGGER.exception("Unexpected exception") + errors["base"] = "unknown" + _LOGGER.debug("setting up extra entry") + return self.async_create_entry( + title=info["title"], + data={SCAN_REGISTERS: info["data"]}, + options=options, + ) return self.async_show_form( step_id="advanced", errors=errors, - data_schema=vol.Schema( - { - vol.Required( - CONF_AC_SYSTEM_VOLTAGE, default=str(AC_VOLTAGES["US (120)"]) - ): SelectSelector( - SelectSelectorConfig( - options=[ - SelectOptionDict(value=str(value), label=key) - for key, value in AC_VOLTAGES.items() - ] - ), - ), - vol.Required( - CONF_NUMBER_OF_PHASES, - default=str(PHASE_CONFIGURATIONS["single phase"]), - ): SelectSelector( - SelectSelectorConfig( - options=[ - SelectOptionDict(value=str(value), label=key) - for key, value in PHASE_CONFIGURATIONS.items() - ] - ), - ), - vol.Required(CONF_AC_CURRENT_LIMIT, default=0): vol.All( - vol.Coerce(int, "must be a number") - ), - vol.Required( - CONF_DC_SYSTEM_VOLTAGE, default=str(DC_VOLTAGES["lifepo4_12v"]) - ): SelectSelector( - SelectSelectorConfig( - options=[ - SelectOptionDict(value=str(value), label=key) - for key, value in DC_VOLTAGES.items() - ] - ), - ), - vol.Required(CONF_DC_CURRENT_LIMIT, default=0): vol.All( - vol.Coerce(int, "must be a number") - ), - vol.Optional(CONF_USE_SLIDERS, default=True): bool, - } - ), + data_schema=STEP_USER_DATA_ADVANCED_SCHEMA, ) - async def async_step_reconfigure(self, user_input: dict[str, Any] | None = None): + async def async_step_reconfigure( + self, user_input: dict[str, Any] | None = None + ) -> Any: """Add reconfigure step to allow to reconfigure a config entry.""" config_entry = self.hass.config_entries.async_get_entry( self.context["entry_id"] @@ -283,16 +420,16 @@ async def async_step_reconfigure(self, user_input: dict[str, Any] | None = None) ) -class parsedEntry: +class ParsedEntry: """Parsed entry.""" - def __init__(self, decoderInfo: RegisterInfo, value): + def __init__(self, decoder_info: RegisterInfo, value: Any) -> None: """Initialize the parsed entry.""" - self.decoderInfo = decoderInfo + self.decoder_info = decoder_info self.value = value -class VictronOptionFlowHandler(config_entries.OptionsFlow): +class VictronOptionFlowHandler(OptionsFlow): # type: ignore[misc] """Handle options.""" logger = logging.getLogger(__name__) @@ -300,9 +437,8 @@ class VictronOptionFlowHandler(config_entries.OptionsFlow): def __init__(self, config_entry: ConfigEntry) -> None: """Initialize options flow.""" self.config_entry = config_entry - self.area = None - async def async_step_advanced(self, user_input=None): + async def async_step_advanced(self, user_input: Any) -> Any: """Handle write support and limit settings if requested.""" config = dict(self.config_entry.options) user_input.pop(CONF_RESCAN, None) @@ -311,7 +447,7 @@ async def async_step_advanced(self, user_input=None): combined_config = {**dict_priority[2], **dict_priority[1]} return self.async_create_entry(title="", data=combined_config) - async def async_step_init_read(self, user_input=None): + async def async_step_init_read(self, user_input: Any) -> Any: """Handle write support and limit settings if requested.""" config = dict(self.config_entry.options) # combine dictionaries with priority given to user_input @@ -330,12 +466,12 @@ async def async_step_init_read(self, user_input=None): self.config_entry, options=combined_config, title="" ) _LOGGER.debug("returning step init because advanced options were selected") - errors = {} + errors: dict = {} # move to dedicated function (the write show form) to allow for re-use return self.init_write_form(errors) return self.async_create_entry(title="", data=combined_config) - async def async_step_init_write(self, user_input=None): + async def async_step_init_write(self, user_input: Any) -> Any: """Handle write support and limit settings if requested.""" config = dict(self.config_entry.options) # remove temp options = @@ -355,7 +491,7 @@ async def async_step_init_write(self, user_input=None): self.config_entry, options=combined_config, title="" ) _LOGGER.debug("returning step init because advanced options were selected") - errors = {} + errors: dict = {} # move to dedicated function (the write show form) to allow for re-use return self.init_read_form(errors) @@ -366,6 +502,7 @@ async def async_step_init( ) -> FlowResult: """Handle a flow initiated by the user.""" errors = {} + info = {} config = dict(self.config_entry.options) @@ -394,15 +531,9 @@ async def async_step_init( return self.async_create_entry(title="", data=config) - if config[CONF_ADVANCED_OPTIONS]: - _LOGGER.debug("advanced options is set") - - return self.init_write_form(errors) - if user_input is None: - return self.init_read_form(errors) - return None + return self.init_read_form(errors) - def init_read_form(self, errors: dict): + def init_read_form(self, errors: dict) -> Any: """Handle read support and limit settings if requested.""" return self.async_show_form( step_id="init_read", @@ -418,7 +549,7 @@ def init_read_form(self, errors: dict): ), ) - def init_write_form(self, errors: dict): + def init_write_form(self, errors: dict) -> Any: """Handle write support and limit settings if requested.""" config = dict(self.config_entry.options) system_ac_voltage_default = self.config_entry.options.get( @@ -500,9 +631,9 @@ def init_write_form(self, errors: dict): ) @staticmethod - def get_dict_key(dict, val): + def get_dict_key(dic: dict, val: Any) -> Any: """Get the key from a dictionary.""" - for key, value in dict.items(): + for key, value in dic.items(): if val == value: return key diff --git a/custom_components/victron/const.py b/custom_components/victron/const.py index 564a8f2..8a1bc0a 100644 --- a/custom_components/victron/const.py +++ b/custom_components/victron/const.py @@ -1,6 +1,7 @@ -"""Constants for the victron integration.""" +"""Constants for the Victron GX modbusTCP integration.""" from enum import Enum +from typing import Any from homeassistant.components.sensor import SensorStateClass from homeassistant.const import ( @@ -59,7 +60,7 @@ class DeviceType(Enum): class STRING: """Class for string data type.""" - def __init__(self, length=1, read_length=None): + def __init__(self, length: int = 1, read_length: Any | None = None) -> None: """Initialize the string data type.""" self.length = length self.readLength = read_length if read_length is not None else length * 2 @@ -77,26 +78,26 @@ def __init__(self, length=1, read_length=None): class EntityType: """Base entityType.""" - def __init__(self, entityTypeName) -> None: + def __init__(self, entity_type_name: str = "read") -> None: """Initialize the entity type.""" - self.entityTypeName = entityTypeName + self.entity_type_name = entity_type_name class ReadEntityType(EntityType): """Read entity type.""" - def __init__(self, entityTypeName: str = "read") -> None: + def __init__(self, entity_type_name: str = "read") -> None: """Initialize the read entity type.""" - super().__init__(entityTypeName=entityTypeName) + super().__init__(entity_type_name=entity_type_name) class TextReadEntityType(ReadEntityType): """Text read entity type.""" - def __init__(self, decodeEnum: Enum) -> None: + def __init__(self, decode_enum: type[Enum]) -> None: """Initialize the text read entity type.""" super().__init__() - self.decodeEnum = decodeEnum + self.decode_enum = decode_enum class BoolReadEntityType(ReadEntityType): @@ -104,7 +105,7 @@ class BoolReadEntityType(ReadEntityType): def __init__(self) -> None: """Initialize the bool read entity type.""" - super().__init__(entityTypeName="bool") + super().__init__(entity_type_name="bool") class ButtonWriteType(EntityType): @@ -112,7 +113,7 @@ class ButtonWriteType(EntityType): def __init__(self) -> None: """Initialize the button write type.""" - super().__init__(entityTypeName="button") + super().__init__(entity_type_name="button") class SwitchWriteType(EntityType): @@ -120,26 +121,26 @@ class SwitchWriteType(EntityType): def __init__(self) -> None: """Initialize the switch write type.""" - super().__init__(entityTypeName="switch") + super().__init__(entity_type_name="switch") class SliderWriteType(EntityType): """Slider write type.""" - def __init__(self, powerType="", negative: bool = False) -> None: + def __init__(self, power_type: str = "", negative: bool = False) -> None: """Initialize the slider write type.""" - super().__init__(entityTypeName="slider") - self.powerType = powerType + super().__init__(entity_type_name="slider") + self.power_type = power_type self.negative = negative class SelectWriteType(EntityType): """Select write type.""" - def __init__(self, optionsEnum: Enum) -> None: + def __init__(self, options_enum: type[Enum]) -> None: """Initialize the select write type.""" - super().__init__(entityTypeName="select") - self.options = optionsEnum + super().__init__(entity_type_name="select") + self.options = options_enum class RegisterInfo: @@ -147,28 +148,28 @@ class RegisterInfo: def __init__( self, - register, - dataType, - unit="", - scale=1, - entityType: EntityType = ReadEntityType(), - step=0, + register: Any, + data_type: Any, + unit: str = "", + scale: float = 1, + entity_type: EntityType = ReadEntityType(), + step: float = 0, ) -> None: """Initialize the register info.""" self.register = register - self.dataType = dataType + self.data_type = data_type self.unit = ( unit - if not isinstance(entityType, TextReadEntityType) - and not isinstance(dataType, STRING) + if not isinstance(entity_type, TextReadEntityType) + and not isinstance(data_type, STRING) else None ) self.scale = scale self.step = step # Only used for writeable entities - self.entityType = entityType + self.entity_type = entity_type - def determine_stateclass(self): + def determine_stateclass(self) -> Any: """Determine the state class.""" if self.unit == UnitOfEnergy.KILO_WATT_HOUR: return SensorStateClass.TOTAL_INCREASING @@ -177,7 +178,7 @@ def determine_stateclass(self): return SensorStateClass.MEASUREMENT -class generic_alarm_ledger(Enum): +class GenericAlarmLedger(Enum): """Generic alarm ledger.""" OK = 0 @@ -241,7 +242,7 @@ class generic_alarm_ledger(Enum): } -class vebus_mode(Enum): +class VebusMode(Enum): """Vebus mode.""" CHARGER = 1 @@ -250,7 +251,7 @@ class vebus_mode(Enum): OFF = 4 -class generic_activeinput(Enum): +class GenericActiveinput(Enum): """Generic active input.""" AC_INPUT_1 = 0 @@ -258,7 +259,7 @@ class generic_activeinput(Enum): DISCONNECTED = 240 -class generic_charger_state(Enum): +class GenericChargerState(Enum): """Generic charger state.""" OFF = 0 @@ -276,7 +277,7 @@ class generic_charger_state(Enum): EXTERNAL_CONTROL = 252 -class vebus_error(Enum): +class VebusError(Enum): """Vebus error.""" OK = 0 @@ -350,162 +351,164 @@ class vebus_error(Enum): 28, UINT16 ), # the number count has no unit of measurement "vebus_activein_activeinput": RegisterInfo( - register=29, dataType=UINT16, entityType=TextReadEntityType(generic_activeinput) + register=29, + data_type=UINT16, + entity_type=TextReadEntityType(GenericActiveinput), ), "vebus_soc": RegisterInfo( 30, UINT16, PERCENTAGE, 10, SliderWriteType(PERCENTAGE, False) ), "vebus_state": RegisterInfo( register=31, - dataType=UINT16, - entityType=TextReadEntityType(generic_charger_state), + data_type=UINT16, + entity_type=TextReadEntityType(GenericChargerState), ), # This has no unit of measurement "vebus_error": RegisterInfo( - register=32, dataType=UINT16, entityType=TextReadEntityType(vebus_error) + register=32, data_type=UINT16, entity_type=TextReadEntityType(VebusError) ), # This has no unit of measurement "vebus_mode": RegisterInfo( - register=33, dataType=UINT16, entityType=SelectWriteType(vebus_mode) + register=33, data_type=UINT16, entity_type=SelectWriteType(VebusMode) ), # This has no unit of measurement "vebus_alarm_hightemperature": RegisterInfo( register=34, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), # This has no unit of measurement "vebus_alarm_lowbattery": RegisterInfo( register=35, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), # This has no unit of measurement "vebus_alarm_overload": RegisterInfo( register=36, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), # This has no unit of measurement "vebus_L1_acpowersetpoint": RegisterInfo( register=37, - dataType=INT16, + data_type=INT16, unit=UnitOfPower.WATT, - entityType=SliderWriteType("AC", True), + entity_type=SliderWriteType("AC", True), ), "vebus_disablecharge": RegisterInfo( - register=38, dataType=UINT16, entityType=SwitchWriteType() + register=38, data_type=UINT16, entity_type=SwitchWriteType() ), # This has no unit of measurement "vebus_disablefeedin": RegisterInfo( - 39, UINT16, entityType=SwitchWriteType() + 39, UINT16, entity_type=SwitchWriteType() ), # This has no unit of measurement "vebus_L2_acpowersetpoint": RegisterInfo( register=40, - dataType=INT16, + data_type=INT16, unit=UnitOfPower.WATT, - entityType=SliderWriteType("AC", True), + entity_type=SliderWriteType("AC", True), ), "vebus_L3_acpowersetpoint": RegisterInfo( register=41, - dataType=INT16, + data_type=INT16, unit=UnitOfPower.WATT, - entityType=SliderWriteType("AC", True), + entity_type=SliderWriteType("AC", True), ), "vebus_alarm_temperaturesensor": RegisterInfo( register=42, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), # This has no unit of measurement "vebus_alarm_voltagesensor": RegisterInfo( register=43, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), # This has no unit of measurement "vebus_alarm_L1_higtemperature": RegisterInfo( register=44, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), # This has no unit of measurement "vebus_alarm_L1_lowbattery": RegisterInfo( register=45, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), # This has no unit of measurement "vebus_alarm_L1_overload": RegisterInfo( register=46, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), # This has no unit of measurement "vebus_alarm_L1_ripple": RegisterInfo( register=47, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), # This has no unit of measurement "vebus_alarm_L2_higtemperature": RegisterInfo( register=48, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), # This has no unit of measurement "vebus_alarm_L2_lowbattery": RegisterInfo( register=49, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), # This has no unit of measurement "vebus_alarm_L2_overload": RegisterInfo( register=50, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), # This has no unit of measurement "vebus_alarm_L2_ripple": RegisterInfo( register=51, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), # This has no unit of measurement "vebus_alarm_L3_higtemperature": RegisterInfo( register=52, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), # This has no unit of measurement "vebus_alarm_L3_lowbattery": RegisterInfo( register=53, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), # This has no unit of measurement "vebus_alarm_L3_overload": RegisterInfo( register=54, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), # This has no unit of measurement "vebus_alarm_L3_ripple": RegisterInfo( register=55, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), # This has no unit of measurement "vebus_pvinverter_disable": RegisterInfo( - register=56, dataType=UINT16, entityType=SwitchWriteType() + register=56, data_type=UINT16, entity_type=SwitchWriteType() ), # This has no unit of measurement "vebus_bms_allowtocharge": RegisterInfo( - register=57, dataType=UINT16, entityType=BoolReadEntityType() + register=57, data_type=UINT16, entity_type=BoolReadEntityType() ), # This has no unit of measurement "vebus_bms_allowtodischarge": RegisterInfo( - register=58, dataType=UINT16, entityType=BoolReadEntityType() + register=58, data_type=UINT16, entity_type=BoolReadEntityType() ), # This has no unit of measurement "vebus_bms_bmsexpected": RegisterInfo( - register=59, dataType=UINT16, entityType=BoolReadEntityType() + register=59, data_type=UINT16, entity_type=BoolReadEntityType() ), # This has no unit of measurement "vebus_bms_error": RegisterInfo( - register=60, dataType=UINT16, entityType=BoolReadEntityType() + register=60, data_type=UINT16, entity_type=BoolReadEntityType() ), # This has no unit of measurement "vebus_battery_temperature": RegisterInfo(61, INT16, UnitOfTemperature.CELSIUS, 10), "vebus_systemreset": RegisterInfo( - register=62, dataType=UINT16, entityType=ButtonWriteType() + register=62, data_type=UINT16, entity_type=ButtonWriteType() ), # This has no unit of measurement "vebus_alarm_phaserotation": RegisterInfo( register=63, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), # This has no unit of measurement "vebus_alarm_gridlost": RegisterInfo( register=64, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), # This has no unit of measurement "vebus_donotfeedinovervoltage": RegisterInfo( - register=65, dataType=UINT16, entityType=SwitchWriteType() + register=65, data_type=UINT16, entity_type=SwitchWriteType() ), # This has no unit of measurement "vebus_L1_maxfeedinpower": RegisterInfo( 66, UINT16, UnitOfPower.WATT, 0.01, SliderWriteType("AC", False) @@ -517,19 +520,19 @@ class vebus_error(Enum): 68, UINT16, UnitOfPower.WATT, 0.01, SliderWriteType("AC", False) ), "vebus_state_ignoreacin1": RegisterInfo( - register=69, dataType=UINT16, entityType=BoolReadEntityType() + register=69, data_type=UINT16, entity_type=BoolReadEntityType() ), # This has no unit of measurement "vebus_state_ignoreacin2": RegisterInfo( - register=70, dataType=UINT16, entityType=BoolReadEntityType() + register=70, data_type=UINT16, entity_type=BoolReadEntityType() ), # This has no unit of measurement "vebus_targetpowerismaxfeedin": RegisterInfo( - register=71, dataType=UINT16, entityType=SwitchWriteType() + register=71, data_type=UINT16, entity_type=SwitchWriteType() ), # This has no unit of measurement "vebus_fixsolaroffsetto100mv": RegisterInfo( - register=72, dataType=UINT16, entityType=SwitchWriteType() + register=72, data_type=UINT16, entity_type=SwitchWriteType() ), # This has no unit of measurement "vebus_sustain": RegisterInfo( - register=73, dataType=UINT16, entityType=BoolReadEntityType() + register=73, data_type=UINT16, entity_type=BoolReadEntityType() ), # This has no unit of measurement "vebus_acin1toacout": RegisterInfo(74, UINT32, UnitOfEnergy.KILO_WATT_HOUR, 100), "vebus_acin1toinverter": RegisterInfo(76, UINT32, UnitOfEnergy.KILO_WATT_HOUR, 100), @@ -558,71 +561,71 @@ class vebus_error(Enum): "battery_soc": RegisterInfo(266, UINT16, PERCENTAGE, 10), "battery_alarm": RegisterInfo( register=267, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "battery_alarm_lowvoltage": RegisterInfo( register=268, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "battery_alarm_highvoltage": RegisterInfo( register=269, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "battery_alarm_lowstartervoltage": RegisterInfo( register=270, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "battery_alarm_highstartervoltage": RegisterInfo( register=271, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "battery_alarm_lowsoc": RegisterInfo( register=272, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "battery_alarm_lowtemperature": RegisterInfo( register=273, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "battery_alarm_hightemperature": RegisterInfo( register=274, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "battery_alarm_midvoltage": RegisterInfo( register=275, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "battery_alarm_lowfusedvoltage": RegisterInfo( register=276, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "battery_alarm_highfusedvoltage": RegisterInfo( register=277, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "battery_alarm_fuseblown": RegisterInfo( register=278, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "battery_alarm_highinternaltemperature": RegisterInfo( register=279, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "battery_relay": RegisterInfo( - register=280, dataType=UINT16, entityType=SwitchWriteType() + register=280, data_type=UINT16, entity_type=SwitchWriteType() ), "battery_history_deepestdischarge": RegisterInfo( 281, UINT16, UnitOfElectricCurrent.AMPERE, -10 @@ -699,43 +702,43 @@ class vebus_error(Enum): ), "battery_alarm_higchargecurrent": RegisterInfo( register=320, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "battery_alarm_highdischargecurrent": RegisterInfo( register=321, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "battery_alarm_cellimbalance": RegisterInfo( register=322, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "battery_alarm_internalfailure": RegisterInfo( register=323, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "battery_alarm_highchargetemperature": RegisterInfo( register=324, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "battery_alarm_lowchargetemperature": RegisterInfo( register=325, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "battery_alarm_lowcellvoltage": RegisterInfo( register=326, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), } -class battery_state(Enum): +class BatteryState(Enum): """Battery state.""" WAIT_START_INIT = 0 @@ -757,7 +760,7 @@ class battery_state(Enum): PRE_CHARGING = 16 -class battery_error(Enum): +class BatteryError(Enum): """Battery error.""" NONE = 0 @@ -800,16 +803,16 @@ class battery_error(Enum): battery_detail_registers = { "battery_state": RegisterInfo( - register=1282, dataType=UINT16, entityType=TextReadEntityType(battery_state) + register=1282, data_type=UINT16, entity_type=TextReadEntityType(BatteryState) ), "battery_error": RegisterInfo( - register=1283, dataType=UINT16, entityType=TextReadEntityType(battery_error) + register=1283, data_type=UINT16, entity_type=TextReadEntityType(BatteryError) ), "battery_system_switch": RegisterInfo( - register=1284, dataType=UINT16, entityType=BoolReadEntityType() + register=1284, data_type=UINT16, entity_type=BoolReadEntityType() ), "battery_balancing": RegisterInfo( - register=1285, dataType=UINT16, entityType=BoolReadEntityType() + register=1285, data_type=UINT16, entity_type=BoolReadEntityType() ), "battery_system_numberofbatteries": RegisterInfo(1286, UINT16), "battery_system_batteriesparallel": RegisterInfo(1287, UINT16), @@ -823,25 +826,25 @@ class battery_error(Enum): ), "battery_diagnostics_shutdownsdueerror": RegisterInfo(1292, UINT16), "battery_diagnostics_lasterror_1": RegisterInfo( - register=1293, dataType=UINT16, entityType=TextReadEntityType(battery_error) + register=1293, data_type=UINT16, entity_type=TextReadEntityType(BatteryError) ), "battery_diagnostics_lasterror_2": RegisterInfo( - register=1294, dataType=UINT16, entityType=TextReadEntityType(battery_error) + register=1294, data_type=UINT16, entity_type=TextReadEntityType(BatteryError) ), "battery_diagnostics_lasterror_3": RegisterInfo( - register=1295, dataType=UINT16, entityType=TextReadEntityType(battery_error) + register=1295, data_type=UINT16, entity_type=TextReadEntityType(BatteryError) ), "battery_diagnostics_lasterror_4": RegisterInfo( - register=1296, dataType=UINT16, entityType=TextReadEntityType(battery_error) + register=1296, data_type=UINT16, entity_type=TextReadEntityType(BatteryError) ), "battery_io_allowtocharge": RegisterInfo( - register=1297, dataType=UINT16, entityType=BoolReadEntityType() + register=1297, data_type=UINT16, entity_type=BoolReadEntityType() ), "battery_io_allowtodischarge": RegisterInfo( - register=1298, dataType=UINT16, entityType=BoolReadEntityType() + register=1298, data_type=UINT16, entity_type=BoolReadEntityType() ), "battery_io_externalrelay": RegisterInfo( - register=1299, dataType=UINT16, entityType=BoolReadEntityType() + register=1299, data_type=UINT16, entity_type=BoolReadEntityType() ), "battery_history_minimumcellvoltage": RegisterInfo( 1300, UINT16, UnitOfElectricPotential.VOLT, 100 @@ -860,14 +863,14 @@ class battery_error(Enum): } -class solarcharger_mode(Enum): +class SolarchargerMode(Enum): """Solar charger mode.""" ON = 1 OFF = 4 -class solarcharger_state(Enum): +class SolarchargerState(Enum): """Solar charger state.""" OFF = 0 @@ -882,7 +885,7 @@ class solarcharger_state(Enum): EXTERNAL_CONTROL = 252 -class solarcharger_equalization_pending(Enum): +class SolarchargerEqualizationPending(Enum): """Solar charger equalization pending.""" NO = 0 @@ -891,7 +894,7 @@ class solarcharger_equalization_pending(Enum): UNAVAILABLE = 3 -class generic_charger_errorcode(Enum): +class GenericChargerErrorcode(Enum): """Generic charger error code.""" NONE = 0 @@ -913,7 +916,7 @@ class generic_charger_errorcode(Enum): INPUT_CURRENT_TOO_HIGH = 34 -class generic_mppoperationmode(Enum): +class GenericMppoperationmode(Enum): """Generic MPP operation mode.""" OFF = 0 @@ -932,11 +935,13 @@ class generic_mppoperationmode(Enum): "solarcharger_battery_temperature": RegisterInfo( 773, INT16, UnitOfTemperature.CELSIUS, 10 ), - "solarcharger_mode": RegisterInfo( - register=774, dataType=UINT16, entityType=SelectWriteType(solarcharger_mode) + "SolarchargerMode": RegisterInfo( + register=774, data_type=UINT16, entity_type=SelectWriteType(SolarchargerMode) ), - "solarcharger_state": RegisterInfo( - register=775, dataType=UINT16, entityType=TextReadEntityType(solarcharger_state) + "SolarchargerState": RegisterInfo( + register=775, + data_type=UINT16, + entity_type=TextReadEntityType(SolarchargerState), ), "solarcharger_pv_voltage": RegisterInfo( 776, UINT16, UnitOfElectricPotential.VOLT, 100 @@ -946,29 +951,29 @@ class generic_mppoperationmode(Enum): ), "solarcharger_equallization_pending": RegisterInfo( register=778, - dataType=UINT16, - entityType=TextReadEntityType(solarcharger_equalization_pending), + data_type=UINT16, + entity_type=TextReadEntityType(SolarchargerEqualizationPending), ), "solarcharger_equalization_time_remaining": RegisterInfo( 779, UINT16, UnitOfTime.SECONDS, 10 ), "solarcharger_relay": RegisterInfo( - register=780, dataType=UINT16, entityType=BoolReadEntityType() + register=780, data_type=UINT16, entity_type=BoolReadEntityType() ), "solarcharger_alarm": RegisterInfo( register=781, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "solarcharger_alarm_lowvoltage": RegisterInfo( register=782, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "solarcharger_alarm_highvoltage": RegisterInfo( register=783, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "solarcharger_yield_today": RegisterInfo( 784, UINT16, UnitOfEnergy.KILO_WATT_HOUR, 10 @@ -980,8 +985,8 @@ class generic_mppoperationmode(Enum): "solarcharger_maxpower_yesterday": RegisterInfo(787, UINT16, UnitOfPower.WATT), "solarcharger_errorcode": RegisterInfo( register=788, - dataType=UINT16, - entityType=TextReadEntityType(generic_charger_errorcode), + data_type=UINT16, + entity_type=TextReadEntityType(GenericChargerErrorcode), ), "solarcharger_yield_power": RegisterInfo(789, UINT16, UnitOfPower.WATT, 10), "solarcharger_yield_user": RegisterInfo( @@ -989,8 +994,8 @@ class generic_mppoperationmode(Enum): ), "solarcharger_mppoperationmode": RegisterInfo( register=791, - dataType=UINT16, - entityType=TextReadEntityType(generic_mppoperationmode), + data_type=UINT16, + entity_type=TextReadEntityType(GenericMppoperationmode), ), } @@ -1065,7 +1070,7 @@ class generic_mppoperationmode(Enum): } -class generic_position(Enum): +class GenericPosition(Enum): """Generic position.""" AC_INPUT_1 = 0 @@ -1075,7 +1080,9 @@ class generic_position(Enum): pvinverter_registers = { "pvinverter_position": RegisterInfo( - register=1026, dataType=UINT16, entityType=TextReadEntityType(generic_position) + register=1026, + data_type=UINT16, + entity_type=TextReadEntityType(GenericPosition), ), "pvinverter_L1_voltage": RegisterInfo( 1027, UINT16, UnitOfElectricPotential.VOLT, 10 @@ -1121,9 +1128,9 @@ class generic_position(Enum): "pvinverter_power_max_capacity": RegisterInfo(1054, UINT32, UnitOfPower.WATT), "pvinverter_powerlimit": RegisterInfo( register=1056, - dataType=UINT32, + data_type=UINT32, unit=UnitOfPower.WATT, - entityType=SliderWriteType("AC", False), + entity_type=SliderWriteType("AC", False), ), } @@ -1141,7 +1148,7 @@ class generic_position(Enum): } -class charger_mode(Enum): +class ChargerMode(Enum): """Charger mode.""" OFF = 0 @@ -1177,48 +1184,48 @@ class charger_mode(Enum): INT16, UnitOfElectricCurrent.AMPERE, 10, - entityType=SliderWriteType("AC", True), + entity_type=SliderWriteType("AC", True), ), - "charger_mode": RegisterInfo( - register=2317, dataType=UINT16, entityType=SelectWriteType(charger_mode) + "ChargerMode": RegisterInfo( + register=2317, data_type=UINT16, entity_type=SelectWriteType(ChargerMode) ), "charger_state": RegisterInfo( register=2318, - dataType=UINT16, - entityType=TextReadEntityType(generic_charger_state), + data_type=UINT16, + entity_type=TextReadEntityType(GenericChargerState), ), "charger_errorcode": RegisterInfo( register=2319, - dataType=UINT16, - entityType=TextReadEntityType(generic_charger_errorcode), + data_type=UINT16, + entity_type=TextReadEntityType(GenericChargerErrorcode), ), "charger_relay": RegisterInfo( - register=2320, dataType=UINT16, entityType=BoolReadEntityType() + register=2320, data_type=UINT16, entity_type=BoolReadEntityType() ), "charger_alarm_lowvoltage": RegisterInfo( register=2321, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "charger_alarm_highvoltage": RegisterInfo( register=2322, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), } settings_registers = { "settings_ess_acpowersetpoint": RegisterInfo( register=2700, - dataType=INT16, + data_type=INT16, unit=UnitOfPower.WATT, - entityType=SliderWriteType("AC", True), + entity_type=SliderWriteType("AC", True), ), "settings_ess_maxchargepercentage": RegisterInfo( - register=2701, dataType=UINT16, unit=PERCENTAGE, entityType=SliderWriteType() + register=2701, data_type=UINT16, unit=PERCENTAGE, entity_type=SliderWriteType() ), "settings_ess_maxdischargepercentage": RegisterInfo( - register=2702, dataType=UINT16, unit=PERCENTAGE, entityType=SliderWriteType() + register=2702, data_type=UINT16, unit=PERCENTAGE, entity_type=SliderWriteType() ), "settings_ess_acpowersetpoint2": RegisterInfo( 2703, INT16, UnitOfPower.WATT, 0.01, SliderWriteType("AC", True) @@ -1228,21 +1235,21 @@ class charger_mode(Enum): ), "settings_ess_maxchargecurrent": RegisterInfo( register=2705, - dataType=INT16, + data_type=INT16, unit=UnitOfElectricCurrent.AMPERE, - entityType=SliderWriteType("DC", True), + entity_type=SliderWriteType("DC", True), ), "settings_ess_maxfeedinpower": RegisterInfo( 2706, INT16, UnitOfPower.WATT, 0.01, SliderWriteType("AC", True) ), "settings_ess_overvoltagefeedin": RegisterInfo( - register=2707, dataType=INT16, entityType=SwitchWriteType() + register=2707, data_type=INT16, entity_type=SwitchWriteType() ), "settings_ess_preventfeedback": RegisterInfo( - register=2708, dataType=INT16, entityType=SwitchWriteType() + register=2708, data_type=INT16, entity_type=SwitchWriteType() ), "settings_ess_feedinpowerlimit": RegisterInfo( - register=2709, dataType=INT16, entityType=BoolReadEntityType() + register=2709, data_type=INT16, entity_type=BoolReadEntityType() ), "settings_systemsetup_maxchargevoltage": RegisterInfo( 2710, @@ -1260,14 +1267,14 @@ class charger_mode(Enum): "gps_course": RegisterInfo(2804, UINT16, "", 100), "gps_speed": RegisterInfo(2805, UINT16, UnitOfSpeed.METERS_PER_SECOND, 100), "gps_fix": RegisterInfo( - register=2806, dataType=UINT16, entityType=BoolReadEntityType() + register=2806, data_type=UINT16, entity_type=BoolReadEntityType() ), "gps_numberofsatellites": RegisterInfo(2807, UINT16), "gps_altitude": RegisterInfo(2808, INT32, UnitOfLength.METERS, 10), } -class ess_batterylife_state(Enum): +class EssBatterylifeState(Enum): """ESS battery life state.""" BL_DISABLED_DUPLICATE_1 = 0 @@ -1285,7 +1292,7 @@ class ess_batterylife_state(Enum): BL_DISABLED_LOC_SOC_RECHARGE = 12 -class ess_mode(Enum): +class EssMode(Enum): """ESS mode.""" SELF_CONSUMPTION_WITH_BATTERY_LIFE = 0 @@ -1297,20 +1304,20 @@ class ess_mode(Enum): settings_ess_registers = { "settings_ess_batterylife_state": RegisterInfo( register=2900, - dataType=UINT16, - entityType=SelectWriteType(ess_batterylife_state), + data_type=UINT16, + entity_type=SelectWriteType(EssBatterylifeState), ), "settings_ess_batterylife_minimumsoc": RegisterInfo( 2901, UINT16, PERCENTAGE, 10, SliderWriteType(), 5 ), "settings_ess_mode": RegisterInfo( - register=2902, dataType=UINT16, entityType=SelectWriteType(ess_mode) + register=2902, data_type=UINT16, entity_type=SelectWriteType(EssMode) ), "settings_ess_batterylife_soclimit": RegisterInfo(2903, UINT16, PERCENTAGE, 10), } -class tank_fluidtype(Enum): +class TankFluidtype(Enum): """Tank fluid type.""" FUEL = 0 @@ -1327,7 +1334,7 @@ class tank_fluidtype(Enum): RAW_WATER = 11 -class tank_status(Enum): +class TankStatus(Enum): """Tank status.""" OK = 0 @@ -1341,13 +1348,13 @@ class tank_status(Enum): tank_registers = { "tank_productid": RegisterInfo(3000, UINT16), "tank_capacity": RegisterInfo(3001, UINT32, UnitOfVolume.CUBIC_METERS, 10000), - "tank_fluidtype": RegisterInfo( - register=3003, dataType=UINT16, entityType=TextReadEntityType(tank_fluidtype) + "TankFluidtype": RegisterInfo( + register=3003, data_type=UINT16, entity_type=TextReadEntityType(TankFluidtype) ), "tank_level": RegisterInfo(3004, UINT16, PERCENTAGE, 10), "tank_remaining": RegisterInfo(3005, UINT32, UnitOfVolume.CUBIC_METERS, 10000), - "tank_status": RegisterInfo( - register=3007, dataType=UINT16, entityType=TextReadEntityType(tank_status) + "TankStatus": RegisterInfo( + register=3007, data_type=UINT16, entity_type=TextReadEntityType(TankStatus) ), } @@ -1373,48 +1380,48 @@ class tank_status(Enum): inverter_alarm_registers = { "inverter_alarm_hightemperature": RegisterInfo( register=3110, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "inverter_alarm_highbatteryvoltage": RegisterInfo( register=3111, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "inverter_alarm_highacoutvoltage": RegisterInfo( register=3112, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "inverter_alarm_lowtemperature": RegisterInfo( register=3113, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "inverter_alarm_lowbatteryvoltage": RegisterInfo( register=3114, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "inverter_alarm_lowacoutvoltage": RegisterInfo( register=3115, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "inverter_alarm_overload": RegisterInfo( register=3116, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "inverter_alarm_ripple": RegisterInfo( register=3117, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), } -class inverter_mode(Enum): +class InverterMode(Enum): """Inverter mode.""" ON = 2 @@ -1425,13 +1432,13 @@ class inverter_mode(Enum): inverter_info_registers = { "inverter_info_firmwareversion": RegisterInfo(3125, UINT16), "inverter_info_mode": RegisterInfo( - register=3126, dataType=UINT16, entityType=SelectWriteType(inverter_mode) + register=3126, data_type=UINT16, entity_type=SelectWriteType(InverterMode) ), "inverter_info_productid": RegisterInfo(3127, UINT16), "inverter_info_state": RegisterInfo( register=3128, - dataType=UINT16, - entityType=TextReadEntityType(generic_charger_state), + data_type=UINT16, + entity_type=TextReadEntityType(GenericChargerState), ), } @@ -1516,13 +1523,13 @@ class inverter_mode(Enum): "inverter_tracker_3_power": RegisterInfo(3167, UINT16, UnitOfPower.WATT), "inverter_alarm_lowsoc": RegisterInfo( register=3168, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), } -class genset_status(Enum): +class GensetStatus(Enum): """Genset status.""" STANDBY = 0 @@ -1538,7 +1545,7 @@ class genset_status(Enum): ERROR = 10 -class genset_errorcode(Enum): +class GensetErrorcode(Enum): """Genset error code.""" NONE = 0 @@ -1655,13 +1662,15 @@ class genset_errorcode(Enum): "genset_L3_frequency": RegisterInfo(3211, UINT16, UnitOfFrequency.HERTZ, 100), "genset_productid": RegisterInfo(3212, UINT16), "genset_statuscode": RegisterInfo( - register=3213, dataType=UINT16, entityType=TextReadEntityType(genset_status) + register=3213, data_type=UINT16, entity_type=TextReadEntityType(GensetStatus) ), - "genset_errorcode": RegisterInfo( - register=3214, dataType=UINT16, entityType=TextReadEntityType(genset_errorcode) + "GensetErrorcode": RegisterInfo( + register=3214, + data_type=UINT16, + entity_type=TextReadEntityType(GensetErrorcode), ), "genset_autostart": RegisterInfo( - register=3215, dataType=UINT16, entityType=BoolReadEntityType() + register=3215, data_type=UINT16, entity_type=BoolReadEntityType() ), "genset_engine_load": RegisterInfo(3216, UINT16, PERCENTAGE), "genset_engine_speed": RegisterInfo(3217, UINT16, REVOLUTIONS_PER_MINUTE), @@ -1681,12 +1690,12 @@ class genset_errorcode(Enum): 3222, UINT16, UnitOfElectricPotential.VOLT, 100 ), "genset_start": RegisterInfo( - register=3223, dataType=UINT16, entityType=SwitchWriteType() + register=3223, data_type=UINT16, entity_type=SwitchWriteType() ), } -class temperature_type(Enum): +class TemperatureType(Enum): """Temperature type.""" BATTERY = 0 @@ -1694,7 +1703,7 @@ class temperature_type(Enum): GENERIC = 2 -class temperature_status(Enum): +class TemperatureStatus(Enum): """Temperature status.""" OK = 0 @@ -1709,16 +1718,18 @@ class temperature_status(Enum): "temperature_productid": RegisterInfo(3300, UINT16), "temperature_scale": RegisterInfo(3301, UINT16, "", 100), "temperature_offset": RegisterInfo(3302, INT16, "", 100), - "temperature_type": RegisterInfo( - register=3303, dataType=UINT16, entityType=TextReadEntityType(temperature_type) + "TemperatureType": RegisterInfo( + register=3303, + data_type=UINT16, + entity_type=TextReadEntityType(TemperatureType), ), "temperature_temperature": RegisterInfo( 3304, INT16, UnitOfTemperature.CELSIUS, 100 ), - "temperature_status": RegisterInfo( + "TemperatureStatus": RegisterInfo( register=3305, - dataType=UINT16, - entityType=TextReadEntityType(temperature_status), + data_type=UINT16, + entity_type=TextReadEntityType(TemperatureStatus), ), "temperature_humidity": RegisterInfo(3306, UINT16, PERCENTAGE, 10), "temperature_batteryvoltage": RegisterInfo( @@ -1733,7 +1744,7 @@ class temperature_status(Enum): } -class digitalinput_state(Enum): +class DigitalinputState(Enum): """Digital input state.""" LOW = 0 @@ -1750,7 +1761,7 @@ class digitalinput_state(Enum): STOPPED = 11 -class digitalinput_type(Enum): +class DigitalinputType(Enum): """Digital input type.""" DOOR = 2 @@ -1764,23 +1775,25 @@ class digitalinput_type(Enum): digitalinput_registers = { "digitalinput_count": RegisterInfo(3420, UINT32), - "digitalinput_state": RegisterInfo( + "DigitalinputState": RegisterInfo( register=3422, - dataType=UINT16, - entityType=TextReadEntityType(digitalinput_state), + data_type=UINT16, + entity_type=TextReadEntityType(DigitalinputState), ), "digitalinput_alarm": RegisterInfo( register=3423, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), - "digitalinput_type": RegisterInfo( - register=3424, dataType=UINT16, entityType=TextReadEntityType(digitalinput_type) + "DigitalinputType": RegisterInfo( + register=3424, + data_type=UINT16, + entity_type=TextReadEntityType(DigitalinputType), ), } -class generator_runningbyconditioncode(Enum): +class GeneratorRunningbyconditioncode(Enum): """Generator running by condition code.""" STOPPED = 0 @@ -1796,7 +1809,7 @@ class generator_runningbyconditioncode(Enum): STOP_ON_AC1 = 10 -class generator_state(Enum): +class GeneratorState(Enum): """Generator state.""" STOPPED = 0 @@ -1804,7 +1817,7 @@ class generator_state(Enum): ERROR = 10 -class generator_error(Enum): +class GeneratorError(Enum): """Generator error.""" NONE = 0 @@ -1814,31 +1827,31 @@ class generator_error(Enum): generator_registers = { "generator_manualstart": RegisterInfo( - register=3500, dataType=UINT16, entityType=SwitchWriteType() + register=3500, data_type=UINT16, entity_type=SwitchWriteType() ), - "generator_runningbyconditioncode": RegisterInfo( + "GeneratorRunningbyconditioncode": RegisterInfo( register=3501, - dataType=UINT16, - entityType=TextReadEntityType(generator_runningbyconditioncode), + data_type=UINT16, + entity_type=TextReadEntityType(GeneratorRunningbyconditioncode), ), "generator_runtime": RegisterInfo(3502, UINT16, UnitOfTime.SECONDS), "generator_quiethours": RegisterInfo( - register=3503, dataType=UINT16, entityType=BoolReadEntityType() + register=3503, data_type=UINT16, entity_type=BoolReadEntityType() ), "generator_runtime_2": RegisterInfo(3504, UINT32, UnitOfTime.SECONDS), - "generator_state": RegisterInfo( - register=3506, dataType=UINT16, entityType=TextReadEntityType(generator_state) + "GeneratorState": RegisterInfo( + register=3506, data_type=UINT16, entity_type=TextReadEntityType(GeneratorState) ), - "generator_error": RegisterInfo( - register=3507, dataType=UINT16, entityType=TextReadEntityType(generator_error) + "GeneratorError": RegisterInfo( + register=3507, data_type=UINT16, entity_type=TextReadEntityType(GeneratorError) ), "generator_alarm_nogeneratoratacin": RegisterInfo( register=3508, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "generator_autostartenabled": RegisterInfo( - register=3509, dataType=UINT16, entityType=SwitchWriteType() + register=3509, data_type=UINT16, entity_type=SwitchWriteType() ), } @@ -1857,7 +1870,7 @@ class generator_error(Enum): evcharger_productid_registers = {"evcharger_productid": RegisterInfo(3800, UINT16)} -class evcharger_mode(Enum): +class EvchargerMode(Enum): """EV charger mode.""" MANUAL = 0 @@ -1865,7 +1878,7 @@ class evcharger_mode(Enum): SCHEDULED = 2 -class evcharger_status(Enum): +class EvchargerStatus(Enum): """EV charger status.""" DISCONNECTED = 0 @@ -1891,12 +1904,12 @@ class evcharger_status(Enum): "evcharger_model": RegisterInfo(3810, STRING(4)), "evcharger_maxcurrent": RegisterInfo( register=3814, - dataType=UINT16, + data_type=UINT16, unit=UnitOfElectricCurrent.AMPERE, - entityType=SliderWriteType("AC", False), + entity_type=SliderWriteType("AC", False), ), - "evcharger_mode": RegisterInfo( - register=3815, dataType=UINT16, entityType=SelectWriteType(evcharger_mode) + "EvchargerMode": RegisterInfo( + register=3815, data_type=UINT16, entity_type=SelectWriteType(EvchargerMode) ), "evcharger_energy_forward": RegisterInfo( 3816, UINT32, UnitOfEnergy.KILO_WATT_HOUR, 100 @@ -1907,20 +1920,24 @@ class evcharger_status(Enum): "evcharger_total_power": RegisterInfo(3821, UINT16, UnitOfPower.WATT), "evcharger_chargingtime": RegisterInfo(3822, UINT16, UnitOfTime.SECONDS, 0.01), "evcharger_current": RegisterInfo(3823, UINT16, UnitOfElectricCurrent.AMPERE), - "evcharger_status": RegisterInfo( - register=3824, dataType=UINT16, entityType=TextReadEntityType(evcharger_status) + "EvchargerStatus": RegisterInfo( + register=3824, + data_type=UINT16, + entity_type=TextReadEntityType(EvchargerStatus), ), "evcharger_setcurrent": RegisterInfo( register=3825, - dataType=UINT16, + data_type=UINT16, unit=UnitOfElectricCurrent.AMPERE, - entityType=SliderWriteType("AC", False), + entity_type=SliderWriteType("AC", False), ), "evcharger_startstop": RegisterInfo( - register=3826, dataType=UINT16, entityType=SwitchWriteType() + register=3826, data_type=UINT16, entity_type=SwitchWriteType() ), "evcharger_position": RegisterInfo( - register=3827, dataType=UINT16, entityType=TextReadEntityType(generic_position) + register=3827, + data_type=UINT16, + entity_type=TextReadEntityType(GenericPosition), ), } @@ -1962,38 +1979,38 @@ class evcharger_status(Enum): ), "fuelcell_alarm_lowvoltage": RegisterInfo( register=4006, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "fuelcell_alarm_highvoltage": RegisterInfo( register=4007, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "fuelcell_alarm_lowstartervoltage": RegisterInfo( register=4008, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "fuelcell_alarm_highstartervoltage": RegisterInfo( register=4009, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "fuelcell_alarm_lowtemperature": RegisterInfo( register=4010, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "fuelcell_alarm_hightemperature": RegisterInfo( register=4011, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), } -class alternator_state(Enum): +class AlternatorState(Enum): """Alternator state.""" OFF = 0 @@ -2006,7 +2023,7 @@ class alternator_state(Enum): EXTERNAL_CONTROL = 252 -class alternator_errorcode(Enum): +class AlternatorErrorcode(Enum): """Alternator error code.""" HIGH_BATTERY_TEMPERATURE = 12 @@ -2058,41 +2075,43 @@ class alternator_errorcode(Enum): ), "alternator_alarm_lowvoltage": RegisterInfo( register=4106, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "alternator_alarm_highvoltage": RegisterInfo( register=4107, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "alternator_alarm_lowstartervoltage": RegisterInfo( register=4108, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "alternator_alarm_highstartervoltage": RegisterInfo( register=4109, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "alternator_alarm_lowtemperature": RegisterInfo( register=4110, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "alternator_alarm_hightemperature": RegisterInfo( register=4111, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), - "alternator_state": RegisterInfo( - register=4112, dataType=UINT16, entityType=TextReadEntityType(alternator_state) + "AlternatorState": RegisterInfo( + register=4112, + data_type=UINT16, + entity_type=TextReadEntityType(AlternatorState), ), - "alternator_errorcode": RegisterInfo( + "AlternatorErrorcode": RegisterInfo( register=4113, - dataType=UINT16, - entityType=TextReadEntityType(alternator_errorcode), + data_type=UINT16, + entity_type=TextReadEntityType(AlternatorErrorcode), ), "alternator_engine_speed": RegisterInfo(4114, UINT16, REVOLUTIONS_PER_MINUTE), "alternator_alternator_speed": RegisterInfo(4115, UINT16, REVOLUTIONS_PER_MINUTE), @@ -2115,33 +2134,33 @@ class alternator_errorcode(Enum): ), "dcsource_alarm_lowvoltage": RegisterInfo( register=4206, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "dcsource_alarm_highvoltage": RegisterInfo( register=4207, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "dcsource_alarm_lowstartervoltage": RegisterInfo( register=4208, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "dcsource_alarm_highstartervoltage": RegisterInfo( register=4209, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "dcsource_alarm_lowtemperature": RegisterInfo( register=4210, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "dcsource_alarm_hightemperature": RegisterInfo( register=4211, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), } @@ -2161,33 +2180,33 @@ class alternator_errorcode(Enum): ), "dcload_alarm_lowvoltage": RegisterInfo( register=4306, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "dcload_alarm_highvoltage": RegisterInfo( register=4307, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "dcload_alarm_lowstartervoltage": RegisterInfo( register=4308, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "dcload_alarm_highstartervoltage": RegisterInfo( register=4309, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "dcload_alarm_lowtemperature": RegisterInfo( register=4310, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "dcload_alarm_hightemperature": RegisterInfo( register=4311, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), } @@ -2210,38 +2229,38 @@ class alternator_errorcode(Enum): ), "dcsystem_alarm_lowvoltage": RegisterInfo( register=4408, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "dcsystem_alarm_highvoltage": RegisterInfo( register=4409, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "dcsystem_alarm_lowstartervoltage": RegisterInfo( register=4410, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "dcsystem_alarm_highstartervoltage": RegisterInfo( register=4411, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "dcsystem_alarm_lowtemperature": RegisterInfo( register=4412, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "dcsystem_alarm_hightemperature": RegisterInfo( register=4413, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), } -class multi_mode(Enum): +class MultiMode(Enum): """Multi mode.""" CHARGER = 1 @@ -2250,7 +2269,7 @@ class multi_mode(Enum): OFF = 4 -class multi_input_type(Enum): +class MultiInputType(Enum): """Multi input type.""" UNUSED = 0 @@ -2305,10 +2324,14 @@ class multi_input_type(Enum): "multi_output_L3_power": RegisterInfo(4518, INT16, UnitOfPower.WATT, 0.1), "multi_output_L1_frequency": RegisterInfo(4519, UINT16, UnitOfFrequency.HERTZ, 100), "multi_input_1_type": RegisterInfo( - register=4520, dataType=UINT16, entityType=TextReadEntityType(multi_input_type) + register=4520, + data_type=UINT16, + entity_type=TextReadEntityType(MultiInputType), ), "multi_input_2_type": RegisterInfo( - register=4521, dataType=UINT16, entityType=TextReadEntityType(multi_input_type) + register=4521, + data_type=UINT16, + entity_type=TextReadEntityType(MultiInputType), ), "multi_input_1_currentlimit": RegisterInfo( 4522, UINT16, UnitOfElectricCurrent.AMPERE, 10, SliderWriteType("AC", False) @@ -2319,8 +2342,8 @@ class multi_input_type(Enum): "multi_numberofphases": RegisterInfo(4524, UINT16), "multi_activein_activeinput": RegisterInfo( register=4525, - dataType=UINT16, - entityType=TextReadEntityType(generic_activeinput), + data_type=UINT16, + entity_type=TextReadEntityType(GenericActiveinput), ), "multi_battery_voltage": RegisterInfo( 4526, UINT16, UnitOfElectricPotential.VOLT, 100 @@ -2334,67 +2357,67 @@ class multi_input_type(Enum): "multi_battery_soc": RegisterInfo(4529, UINT16, PERCENTAGE, 10), "multi_state": RegisterInfo( register=4530, - dataType=UINT16, - entityType=TextReadEntityType(generic_charger_state), + data_type=UINT16, + entity_type=TextReadEntityType(GenericChargerState), ), - "multi_mode": RegisterInfo( - register=4531, dataType=UINT16, entityType=SelectWriteType(multi_mode) + "MultiMode": RegisterInfo( + register=4531, data_type=UINT16, entity_type=SelectWriteType(MultiMode) ), "multi_alarm_hightemperature": RegisterInfo( register=4532, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "multi_alarm_highvoltage": RegisterInfo( register=4533, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "multi_alarm_highvoltageacout": RegisterInfo( register=4534, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "multi_alarm_lowtemperature": RegisterInfo( register=4535, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "multi_alarm_lowvoltage": RegisterInfo( register=4536, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "multi_alarm_lowvoltageacout": RegisterInfo( register=4537, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "multi_alarm_overload": RegisterInfo( register=4538, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "multi_alarm_ripple": RegisterInfo( register=4539, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), "multi_yield_pv_power": RegisterInfo(4540, UINT16, UnitOfPower.WATT), "multi_yield_user": RegisterInfo(4541, UINT16, UnitOfEnergy.KILO_WATT_HOUR, 10), "multi_relay": RegisterInfo( - register=4542, dataType=UINT16, entityType=BoolReadEntityType() + register=4542, data_type=UINT16, entity_type=BoolReadEntityType() ), "multi_mppoperationmode": RegisterInfo( register=4543, - dataType=UINT16, - entityType=TextReadEntityType(generic_mppoperationmode), + data_type=UINT16, + entity_type=TextReadEntityType(GenericMppoperationmode), ), "multi_pv_voltage": RegisterInfo(4544, UINT16, UnitOfElectricPotential.VOLT, 10), "multi_errorcode": RegisterInfo( register=4545, - dataType=UINT16, - entityType=TextReadEntityType(generic_charger_errorcode), + data_type=UINT16, + entity_type=TextReadEntityType(GenericChargerErrorcode), ), "multi_energy_acin1toacout": RegisterInfo( 4546, UINT32, UnitOfEnergy.KILO_WATT_HOUR, 100 @@ -2512,13 +2535,13 @@ class multi_input_type(Enum): "multi_tracker_3_power": RegisterInfo(4601, UINT16, UnitOfPower.WATT), "multi_alarm_lowsoc": RegisterInfo( register=4602, - dataType=UINT16, - entityType=TextReadEntityType(generic_alarm_ledger), + data_type=UINT16, + entity_type=TextReadEntityType(GenericAlarmLedger), ), } -class register_input_source(Enum): +class RegisterInputSource(Enum): """Input source.""" UNKNOWN = 0 @@ -2531,10 +2554,10 @@ class register_input_source(Enum): system_registers = { "system_serial": RegisterInfo(800, STRING(6)), "system_relay_0": RegisterInfo( - register=806, dataType=UINT16, entityType=SwitchWriteType() + register=806, data_type=UINT16, entity_type=SwitchWriteType() ), "system_relay_1": RegisterInfo( - register=807, dataType=UINT16, entityType=SwitchWriteType() + register=807, data_type=UINT16, entity_type=SwitchWriteType() ), "system_pvonoutput_L1": RegisterInfo(808, UINT16, UnitOfPower.WATT), "system_pvonoutput_L2": RegisterInfo(809, UINT16, UnitOfPower.WATT), @@ -2556,13 +2579,13 @@ class register_input_source(Enum): "system_genset_L3": RegisterInfo(825, INT16, UnitOfPower.WATT), "system_input_source": RegisterInfo( register=826, - dataType=INT16, - entityType=TextReadEntityType(register_input_source), + data_type=INT16, + entity_type=TextReadEntityType(RegisterInputSource), ), } -class system_battery_state(Enum): +class SystemBatteryState(Enum): """Battery state.""" IDLE = 0 @@ -2581,8 +2604,8 @@ class system_battery_state(Enum): "system_battery_soc": RegisterInfo(843, UINT16, PERCENTAGE), "system_battery_state": RegisterInfo( register=844, - dataType=UINT16, - entityType=TextReadEntityType(system_battery_state), + data_type=UINT16, + entity_type=TextReadEntityType(SystemBatteryState), ), "system_battery_amphours": RegisterInfo( 845, UINT16, UnitOfElectricCurrent.AMPERE, -10 diff --git a/custom_components/victron/coordinator.py b/custom_components/victron/coordinator.py index d0a362c..964dcaa 100644 --- a/custom_components/victron/coordinator.py +++ b/custom_components/victron/coordinator.py @@ -5,11 +5,14 @@ from collections import OrderedDict from datetime import timedelta import logging +from typing import Any import pymodbus if "3.7.0" <= pymodbus.__version__ <= "3.7.4": - from pymodbus.pdu.register_read_message import ReadHoldingRegistersResponse + from pymodbus.pdu.register_read_message import ( # pylint: disable=no-name-in-module + ReadHoldingRegistersResponse, + ) else: from pymodbus.pdu.register_message import ReadHoldingRegistersResponse @@ -17,6 +20,7 @@ from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed +from .config_flow import VictronHub from .const import ( DOMAIN, INT16, @@ -27,12 +31,11 @@ RegisterInfo, register_info_dict, ) -from .hub import VictronHub _LOGGER = logging.getLogger(__name__) -class victronEnergyDeviceUpdateCoordinator(DataUpdateCoordinator): +class VictronEnergyDeviceUpdateCoordinator(DataUpdateCoordinator): """Gather data for the energy device.""" api: VictronHub @@ -41,8 +44,8 @@ def __init__( self, hass: HomeAssistant, host: str, - port: str, - decodeInfo: OrderedDict, + port: int, + decode_info: OrderedDict, interval: int, ) -> None: """Initialize Update Coordinator.""" @@ -52,7 +55,7 @@ def __init__( ) self.api = VictronHub(host, port) self.api.connect() - self.decodeInfo = decodeInfo + self.decode_info = decode_info self.interval = interval # async def force_update_data(self) -> None: @@ -61,18 +64,18 @@ def __init__( async def _async_update_data(self) -> dict: """Fetch all device and sensor data from api.""" - data = "" - """Get the latest data from victron""" + self.data: dict[str, Any] + # Get the latest data from victron self.logger.debug("Fetching victron data") - self.logger.debug(self.decodeInfo) + self.logger.debug(self.decode_info) - parsed_data = OrderedDict() + parsed_data: OrderedDict = OrderedDict() unavailable_entities = OrderedDict() if self.data is None: self.data = {"data": OrderedDict(), "availability": OrderedDict()} - for unit, registerInfo in self.decodeInfo.items(): + for unit, registerInfo in self.decode_info.items(): for name in registerInfo: data = await self.fetch_registers(unit, register_info_dict[name]) # TODO safety check if result is actual data if not unavailable @@ -102,7 +105,7 @@ async def _async_update_data(self) -> dict: unavailable_entities[full_key] = True return { - "register_set": self.decodeInfo, + "register_set": self.decode_info, "data": parsed_data, "availability": unavailable_entities, } @@ -110,7 +113,7 @@ async def _async_update_data(self) -> dict: def parse_register_data( self, buffer: ReadHoldingRegistersResponse, - registerInfo: OrderedDict[str, RegisterInfo], + register_info: OrderedDict[str, RegisterInfo] | dict, unit: int, ) -> dict: """Parse the register data using convert_from_registers.""" @@ -118,22 +121,22 @@ def parse_register_data( registers = buffer.registers offset = 0 - for key, value in registerInfo.items(): + for key, value in register_info.items(): full_key = f"{unit}.{key}" count = 0 - if value.dataType in (INT16, UINT16): + if value.data_type in (INT16, UINT16): count = 1 - elif value.dataType in (INT32, UINT32): + elif value.data_type in (INT32, UINT32): count = 2 - elif isinstance(value.dataType, STRING): - count = value.dataType.length + elif isinstance(value.data_type, STRING): + count = value.data_type.length segment = registers[offset : offset + count] - if isinstance(value.dataType, STRING): + if isinstance(value.data_type, STRING): raw = self.api.convert_string_from_register(segment) decoded_data[full_key] = raw else: - raw = self.api.convert_number_from_register(segment, value.dataType) + raw = self.api.convert_number_from_register(segment, value.data_type) # _LOGGER.warning("trying to decode %s with value %s", key, raw) decoded_data[full_key] = self.decode_scaling( raw, value.scale, value.unit @@ -142,13 +145,15 @@ def parse_register_data( return decoded_data - def decode_scaling(self, number, scale, unit): + @staticmethod + def decode_scaling(number: Any, scale: Any, unit: Any) -> Any: """Decode the scaling.""" if unit == "" and scale == 1: return round(number) return number / scale - def encode_scaling(self, value, unit, scale): + @staticmethod + def encode_scaling(value: Any, unit: Any, scale: Any) -> Any: """Encode the scaling.""" if scale == 0: return value @@ -156,34 +161,35 @@ def encode_scaling(self, value, unit, scale): return int(round(value)) return int(value * scale) - def get_data(self): + def get_data(self) -> Any: """Return the data.""" return self.data - async def async_update_local_entry(self, key, value): + async def async_update_local_entry(self, key: Any, value: Any) -> Any: """Update the local entry.""" data = self.data - data["data"][key] = value - self.async_set_updated_data(data) + if data: + data["data"][key] = value + self.async_set_updated_data(data) - await self.async_request_refresh() + await self.async_request_refresh() - def processed_data(self): + def processed_data(self) -> dict[Any, Any]: """Return the processed data.""" return self.data - async def fetch_registers(self, unit, registerData): + async def fetch_registers(self, unit: Any, register_data: Any) -> Any: """Fetch the registers.""" try: # run api_update in async job return await self.hass.async_add_executor_job( - self.api_update, unit, registerData + self.api_update, unit, register_data ) except HomeAssistantError as e: raise UpdateFailed("Fetching registers failed") from e - def write_register(self, unit, address, value): + def write_register(self, unit: Any, address: Any, value: Any) -> Any: """Write to the register.""" # try: @@ -193,18 +199,18 @@ def write_register(self, unit, address, value): # TODO raise specific write error # _LOGGER.error("failed to write to option:", e - def api_write(self, unit, address, value): + def api_write(self, unit: Any, address: Any, value: Any) -> Any: """Write to the api.""" # recycle connection return self.api.write_register(unit=unit, address=address, value=value) - def api_update(self, unit, registerInfo): + def api_update(self, unit: Any, register_info: Any) -> Any: """Update the api.""" # recycle connection return self.api.read_holding_registers( unit=unit, - address=self.api.get_first_register_id(registerInfo), - count=self.api.calculate_register_count(registerInfo), + address=self.api.get_first_register_id(register_info), + count=self.api.calculate_register_count(register_info), ) @@ -215,7 +221,7 @@ class DecodeDataTypeUnsupported(Exception): class DataEntry: """Data entry class.""" - def __init__(self, unit, value) -> None: + def __init__(self, unit: Any, value: Any) -> None: """Initialize the data entry.""" self.unit = unit self.value = value diff --git a/custom_components/victron/base.py b/custom_components/victron/entity.py similarity index 82% rename from custom_components/victron/base.py rename to custom_components/victron/entity.py index 04722b9..a0e8e2f 100644 --- a/custom_components/victron/base.py +++ b/custom_components/victron/entity.py @@ -2,26 +2,27 @@ from collections.abc import Callable from dataclasses import dataclass +from typing import Any from homeassistant.helpers.entity import EntityDescription from homeassistant.helpers.typing import StateType -@dataclass +@dataclass(frozen=True) class VictronBaseEntityDescription(EntityDescription): """An extension of EntityDescription for Victron components.""" @staticmethod - def lambda_func(): + def lambda_func() -> Any: """Return an entitydescription.""" return lambda data, slave, key: data["data"][str(slave) + "." + str(key)] - slave: int = None + slave: int | None = None value_fn: Callable[[dict], StateType] = lambda_func() -@dataclass +@dataclass(frozen=True) class VictronWriteBaseEntityDescription(VictronBaseEntityDescription): """An extension of VictronBaseEntityDescription for writeable Victron components.""" - address: int = None + address: int | None = None diff --git a/custom_components/victron/hub.py b/custom_components/victron/hub.py deleted file mode 100644 index 6fb6d84..0000000 --- a/custom_components/victron/hub.py +++ /dev/null @@ -1,143 +0,0 @@ -"""Support for Victron Energy devices.""" - -from collections import OrderedDict -import logging -import threading - -from packaging import version -import pymodbus -from pymodbus.client import ModbusTcpClient - -from homeassistant.exceptions import HomeAssistantError - -from .const import ( - INT16, - INT32, - STRING, - UINT16, - UINT32, - register_info_dict, - valid_unit_ids, -) - -_LOGGER = logging.getLogger(__name__) - - -class VictronHub: - """Victron Hub.""" - - def __init__(self, host: str, port: int) -> None: - """Initialize.""" - self.host = host - self.port = port - self._client = ModbusTcpClient(host=self.host, port=self.port) - self._lock = threading.Lock() - - def is_still_connected(self): - """Check if the connection is still open.""" - return self._client.is_socket_open() - - def convert_string_from_register(self, segment, string_encoding="ascii"): - """Convert from registers to the appropriate data type.""" - if version.parse("3.8.0") <= version.parse(pymodbus.__version__) <= version.parse("3.8.4"): - return self._client.convert_from_registers( - segment, self._client.DATATYPE.STRING - ).split("\x00")[0] - return self._client.convert_from_registers( - segment, self._client.DATATYPE.STRING, string_encoding=string_encoding - ).split("\x00")[0] - - def convert_number_from_register(self, segment, dataType): - """Convert from registers to the appropriate data type.""" - if dataType == UINT16: - raw = self._client.convert_from_registers( - segment, data_type=self._client.DATATYPE.UINT16 - ) - elif dataType == INT16: - raw = self._client.convert_from_registers( - segment, data_type=self._client.DATATYPE.INT16 - ) - elif dataType == UINT32: - raw = self._client.convert_from_registers( - segment, data_type=self._client.DATATYPE.UINT32 - ) - elif dataType == INT32: - raw = self._client.convert_from_registers( - segment, data_type=self._client.DATATYPE.INT32 - ) - return raw - - def connect(self): - """Connect to the Modbus TCP server.""" - return self._client.connect() - - def disconnect(self): - """Disconnect from the Modbus TCP server.""" - if self._client.is_socket_open(): - return self._client.close() - return None - - def write_register(self, unit, address, value): - """Write a register.""" - slave = int(unit) if unit else 1 - return self._client.write_register(address=address, value=value, slave=slave) - - def read_holding_registers(self, unit, address, count): - """Read holding registers.""" - slave = int(unit) if unit else 1 - return self._client.read_holding_registers( - address=address, count=count, slave=slave - ) - - def calculate_register_count(self, registerInfoDict: OrderedDict): - """Calculate the number of registers to read.""" - first_key = next(iter(registerInfoDict)) - last_key = next(reversed(registerInfoDict)) - end_correction = 1 - if registerInfoDict[last_key].dataType in (INT32, UINT32): - end_correction = 2 - elif isinstance(registerInfoDict[last_key].dataType, STRING): - end_correction = registerInfoDict[last_key].dataType.length - - return ( - registerInfoDict[last_key].register - registerInfoDict[first_key].register - ) + end_correction - - def get_first_register_id(self, registerInfoDict: OrderedDict): - """Return first register id.""" - first_register = next(iter(registerInfoDict)) - return registerInfoDict[first_register].register - - def determine_present_devices(self): - """Determine which devices are present.""" - valid_devices = {} - - for unit in valid_unit_ids: - working_registers = [] - for key, register_definition in register_info_dict.items(): - # VE.CAN device zero is present under unit 100. This seperates non system / settings entities into the seperate can device - if unit == 100 and not key.startswith(("settings", "system")): - continue - - try: - address = self.get_first_register_id(register_definition) - count = self.calculate_register_count(register_definition) - result = self.read_holding_registers(unit, address, count) - if result.isError(): - _LOGGER.debug( - "result is error for unit: %s address: %s count: %s", - unit, - address, - count, - ) - else: - working_registers.append(key) - except HomeAssistantError as e: - _LOGGER.error(e) - - if len(working_registers) > 0: - valid_devices[unit] = working_registers - else: - _LOGGER.debug("no registers found for unit: %s", unit) - - return valid_devices diff --git a/custom_components/victron/manifest.json b/custom_components/victron/manifest.json index 49c4548..d4b932e 100644 --- a/custom_components/victron/manifest.json +++ b/custom_components/victron/manifest.json @@ -1,20 +1,16 @@ { "domain": "victron", - "name": "victron", + "name": "Victron GX modbusTCP", "codeowners": [ "@sfstar" ], "config_flow": true, "dependencies": [], - "documentation": "https://github.com/sfstar/hass-victron", + "documentation": "https://www.home-assistant.io/integrations/victron", "homekit": {}, - "integration_type": "hub", "iot_class": "local_polling", - "issue_tracker": "https://github.com/sfstar/hass-victron/issues", - "requirements": [ - "pymodbus>=3.8.0" - ], + "quality_scale": "?", + "requirements": ["pymodbus==3.11.1"], "ssdp": [], - "version": "v0.0.0", "zeroconf": [] } diff --git a/custom_components/victron/number.py b/custom_components/victron/number.py index c489fd5..3358559 100644 --- a/custom_components/victron/number.py +++ b/custom_components/victron/number.py @@ -4,6 +4,7 @@ from dataclasses import dataclass import logging +from typing import Any from homeassistant import config_entries from homeassistant.components.number import ( @@ -14,16 +15,15 @@ ) from homeassistant.const import ( PERCENTAGE, + EntityCategory, UnitOfElectricCurrent, UnitOfElectricPotential, UnitOfPower, ) from homeassistant.core import HomeAssistant -from homeassistant.helpers import entity -from homeassistant.helpers.entity import EntityCategory +from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback -from .base import VictronWriteBaseEntityDescription from .const import ( CONF_AC_CURRENT_LIMIT, CONF_AC_SYSTEM_VOLTAGE, @@ -37,7 +37,8 @@ SliderWriteType, register_info_dict, ) -from .coordinator import victronEnergyDeviceUpdateCoordinator +from .coordinator import VictronEnergyDeviceUpdateCoordinator +from .entity import VictronWriteBaseEntityDescription _LOGGER = logging.getLogger(__name__) @@ -48,11 +49,11 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up victron switch devices.""" - victron_coordinator: victronEnergyDeviceUpdateCoordinator = hass.data[DOMAIN][ + victron_coordinator: VictronEnergyDeviceUpdateCoordinator = hass.data[DOMAIN][ config_entry.entry_id ] _LOGGER.debug("attempting to setup number entities") - descriptions = [] + descriptions: list = [] _LOGGER.debug(config_entry) # TODO cleanup if config_entry.options[CONF_ADVANCED_OPTIONS]: @@ -61,12 +62,12 @@ async def async_setup_entry( for name in registerLedger: for register_name, registerInfo in register_info_dict[name].items(): _LOGGER.debug( - "unit == %s registerLedger == %s registerInfo", + "unit == %s registerLedger == %s register_info", slave, registerLedger, ) - if isinstance(registerInfo.entityType, SliderWriteType): + if isinstance(registerInfo.entity_type, SliderWriteType): description = VictronEntityDescription( key=register_name, name=register_name.replace("_", " "), @@ -78,35 +79,35 @@ async def async_setup_entry( native_min_value=determine_min_value( registerInfo.unit, config_entry.options, - registerInfo.entityType.powerType, - registerInfo.entityType.negative, + registerInfo.entity_type.power_type, + registerInfo.entity_type.negative, ), native_max_value=determine_max_value( registerInfo.unit, config_entry.options, - registerInfo.entityType.powerType, + registerInfo.entity_type.power_type, ), entity_category=EntityCategory.CONFIG, address=registerInfo.register, - scale=registerInfo.scale, + scale=registerInfo.scale, # type: ignore[arg-type] native_step=registerInfo.step, ) _LOGGER.debug("composed description == %s", descriptions) descriptions.append(description) - entities = [] - entity = {} + _entities = [] + _entity: dict = {} for description in descriptions: - entity = description - entities.append(VictronNumber(victron_coordinator, entity)) + _entity = description + _entities.append(VictronNumber(victron_coordinator, _entity)) _LOGGER.debug("adding number") - async_add_entities(entities) + async_add_entities(_entities) _LOGGER.debug("adding numbering") def determine_min_value( - unit, config_entry: config_entries.ConfigEntry, powerType, negative: bool -) -> int: + unit: Any, config_entry: Any, power_type: Any, negative: bool +) -> Any: """Determine the minimum value for a number entity.""" if unit == PERCENTAGE: return 0 @@ -123,7 +124,7 @@ def determine_min_value( * int(config_entry[CONF_NUMBER_OF_PHASES]) * config_entry[CONF_AC_CURRENT_LIMIT] ) - if powerType == "AC" + if power_type == "AC" else ( int(config_entry[CONF_DC_SYSTEM_VOLTAGE].dc_voltage) * config_entry[CONF_DC_CURRENT_LIMIT] @@ -135,18 +136,16 @@ def determine_min_value( return 0 if unit == UnitOfElectricCurrent.AMPERE: if negative: - if powerType == "AC": + if power_type == "AC": return -config_entry[CONF_AC_CURRENT_LIMIT] - if powerType == "DC": + if power_type == "DC": return -config_entry[CONF_DC_CURRENT_LIMIT] return None return 0 return 0 -def determine_max_value( - unit, config_entry: config_entries.ConfigEntry, powerType -) -> int: +def determine_max_value(unit: Any, config_entry: Any, power_type: Any) -> Any: """Determine the maximum value for a number entity.""" if unit == PERCENTAGE: return 100 @@ -162,7 +161,7 @@ def determine_max_value( * int(config_entry[CONF_NUMBER_OF_PHASES]) * config_entry[CONF_AC_CURRENT_LIMIT] ) - if powerType == "AC" + if power_type == "AC" else ( int(config_entry[CONF_DC_SYSTEM_VOLTAGE]) * config_entry[CONF_DC_CURRENT_LIMIT] @@ -170,15 +169,15 @@ def determine_max_value( ) return round(max_value / 100) * 100 if unit == UnitOfElectricCurrent.AMPERE: - if powerType == "AC": + if power_type == "AC": return config_entry[CONF_AC_CURRENT_LIMIT] - if powerType == "DC": + if power_type == "DC": return config_entry[CONF_DC_CURRENT_LIMIT] return None return 0 -@dataclass +@dataclass(frozen=True) class VictronNumberMixin: """A class that describes number entities.""" @@ -186,14 +185,14 @@ class VictronNumberMixin: mode: bool | None = None -@dataclass +@dataclass(frozen=True) class VictronNumberStep: """A class that adds stepping to number entities.""" native_step: float = 0 -@dataclass +@dataclass(frozen=True) class VictronEntityDescription( NumberEntityDescription, VictronWriteBaseEntityDescription, @@ -203,7 +202,7 @@ class VictronEntityDescription( """Describes victron number entity.""" # Overwrite base entitydescription property to resolve automatic property ordering issues when a mix of non-default and default properties are used - key: str | None = None + key: str = "" class VictronNumber(NumberEntity): @@ -213,7 +212,7 @@ class VictronNumber(NumberEntity): def __init__( self, - coordinator: victronEnergyDeviceUpdateCoordinator, + coordinator: VictronEnergyDeviceUpdateCoordinator, description: VictronEntityDescription, ) -> None: """Initialize the entity.""" @@ -254,14 +253,14 @@ async def async_set_native_value(self, value: float) -> None: await self.coordinator.async_update_local_entry(self.data_key, int(value)) @property - def native_value(self) -> float: + def native_value(self) -> Any: """Return the state of the entity.""" - value = self.description.value_fn( + value = self.description.value_fn( # type: ignore[call-arg] data=self.coordinator.processed_data(), slave=self.description.slave, key=self.description.key, ) - if value > round( + if value and value > round( UINT16_MAX / 2 ): # Half of the UINT16 is reserved for positive and half for negative values value = value - UINT16_MAX @@ -274,7 +273,10 @@ def native_step(self) -> float | None: self.description.mode != NumberMode.SLIDER ): # allow users to skip stepping in case of box mode return None - if self.description.native_step > 0: + if ( + self.description.native_step is not None + and self.description.native_step > 0.0 + ): return self.description.native_step _max = self.native_max_value _min = self.native_min_value @@ -287,27 +289,27 @@ def native_step(self) -> float | None: return 1 @property - def native_min_value(self) -> float: + def native_min_value(self) -> Any: """Return the minimum value of the entity.""" return self.description.native_min_value @property - def native_max_value(self) -> float: + def native_max_value(self) -> Any: """Return the maximum value of the entity.""" return self.description.native_max_value @property - def available(self) -> bool: + def available(self) -> Any: """Return True if entity is available.""" full_key = str(self.description.slave) + "." + self.description.key return self.coordinator.processed_data()["availability"][full_key] @property - def device_info(self) -> entity.DeviceInfo: + def device_info(self) -> DeviceInfo: """Return the device info.""" - return entity.DeviceInfo( - identifiers={(DOMAIN, self.unique_id.split("_")[0])}, - name=self.unique_id.split("_")[1], - model=self.unique_id.split("_")[0], + return DeviceInfo( + identifiers={(DOMAIN, self.unique_id.split("_", maxsplit=1)[0])}, + name=self.unique_id.split("_", maxsplit=1)[1], + model=self.unique_id.split("_", maxsplit=1)[0], manufacturer="victron", ) diff --git a/custom_components/victron/quality_scale.yaml b/custom_components/victron/quality_scale.yaml new file mode 100644 index 0000000..db1a232 --- /dev/null +++ b/custom_components/victron/quality_scale.yaml @@ -0,0 +1,62 @@ +rules: + # Bronze + action-setup: done + appropriate-polling: done + brands: done + common-modules: done + config-flow-test-coverage: done + config-flow: done + dependency-transparency: done + docs-actions: todo + docs-high-level-description: todo + docs-installation-instructions: todo + docs-removal-instructions: todo + entity-event-setup: + status: exempt + comment: The integration does not use events. + entity-unique-id: done + has-entity-name: done + runtime-data: done + test-before-configure: done + test-before-setup: done + unique-config-entry: done + + # Silver + action-exceptions: todo + config-entry-unloading: done + docs-configuration-parameters: todo + docs-installation-parameters: todo + entity-unavailable: todo + integration-owner: done + log-when-unavailable: todo + parallel-updates: todo + reauthentication-flow: todo + test-coverage: todo + + # Gold + devices: todo + diagnostics: todo + discovery-update-info: todo + discovery: todo + docs-data-update: todo + docs-examples: todo + docs-known-limitations: todo + docs-supported-devices: todo + docs-supported-functions: todo + docs-troubleshooting: todo + docs-use-cases: todo + dynamic-devices: todo + entity-category: todo + entity-device-class: done + entity-disabled-by-default: todo + entity-translations: todo + exception-translations: todo + icon-translations: todo + reconfiguration-flow: todo + repair-issues: todo + stale-devices: todo + + # Platinum + async-dependency: todo + inject-websession: todo + strict-typing: todo diff --git a/custom_components/victron/select.py b/custom_components/victron/select.py index 1b990be..11df45c 100644 --- a/custom_components/victron/select.py +++ b/custom_components/victron/select.py @@ -4,8 +4,8 @@ from dataclasses import dataclass from datetime import timedelta -from enum import Enum import logging +from typing import Any from homeassistant.components.select import ( DOMAIN as SELECT_DOMAIN, @@ -14,14 +14,15 @@ ) from homeassistant.config_entries import ConfigEntry from homeassistant.core import HassJob, HomeAssistant -from homeassistant.helpers import entity, event +from homeassistant.helpers import event +from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity -from homeassistant.util import utcnow +from homeassistant.util.dt import utcnow -from .base import VictronWriteBaseEntityDescription from .const import CONF_ADVANCED_OPTIONS, DOMAIN, SelectWriteType, register_info_dict -from .coordinator import victronEnergyDeviceUpdateCoordinator +from .coordinator import VictronEnergyDeviceUpdateCoordinator +from .entity import VictronWriteBaseEntityDescription _LOGGER = logging.getLogger(__name__) @@ -32,7 +33,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up victron select devices.""" - victron_coordinator: victronEnergyDeviceUpdateCoordinator = hass.data[DOMAIN][ + victron_coordinator: VictronEnergyDeviceUpdateCoordinator = hass.data[DOMAIN][ config_entry.entry_id ] _LOGGER.debug("attempting to setup select entities") @@ -43,9 +44,9 @@ async def async_setup_entry( for slave, registerLedger in register_set.items(): for name in registerLedger: for register_name, registerInfo in register_info_dict[name].items(): - if isinstance(registerInfo.entityType, SelectWriteType): + if isinstance(registerInfo.entity_type, SelectWriteType): _LOGGER.debug( - "unit == %s registerLedger == %s registerInfo", + "unit == %s registerLedger == %s register_info", slave, registerLedger, ) @@ -54,30 +55,30 @@ async def async_setup_entry( key=register_name, name=register_name.replace("_", " "), slave=slave, - options=registerInfo.entityType.options, + options=registerInfo.entity_type.options, address=registerInfo.register, ) descriptions.append(description) _LOGGER.debug("composed description == %s", description) - entities = [] - entity = {} - for description in descriptions: - entity = description - entities.append(VictronSelect(hass, victron_coordinator, entity)) + _entities = [ + VictronSelect(hass, victron_coordinator, description) + for description in descriptions + ] _LOGGER.debug("adding selects") - _LOGGER.debug(entities) - async_add_entities(entities) + _LOGGER.debug(_entities) + async_add_entities(_entities) -@dataclass +@dataclass(frozen=True) class VictronEntityDescription( - SelectEntityDescription, VictronWriteBaseEntityDescription + SelectEntityDescription, + VictronWriteBaseEntityDescription, ): """Describes victron sensor entity.""" - options: Enum = None + options: Any class VictronSelect(CoordinatorEntity, SelectEntity): @@ -88,13 +89,12 @@ class VictronSelect(CoordinatorEntity, SelectEntity): def __init__( self, hass: HomeAssistant, - coordinator: victronEnergyDeviceUpdateCoordinator, + coordinator: VictronEnergyDeviceUpdateCoordinator, description: VictronEntityDescription, ) -> None: """Initialize the select.""" self._attr_native_value = None _LOGGER.debug("select init") - self.coordinator = coordinator self.description: VictronEntityDescription = description # this needs to be changed to allow multiple of the same type self._attr_name = f"{description.name}" @@ -113,7 +113,7 @@ async def async_update(self) -> None: """Get the latest data and updates the states.""" _LOGGER.debug("select_async_update") try: - self._attr_native_value = self.description.value_fn( + self._attr_native_value = self.description.value_fn( # type: ignore[call-arg] self.coordinator.processed_data(), self.description.slave, self.description.key, @@ -136,10 +136,10 @@ async def async_update(self) -> None: ) @property - def current_option(self) -> str: + def current_option(self) -> Any: """Return the currently selected option.""" return self.description.options( - self.description.value_fn( + self.description.value_fn( # type: ignore[call-arg] self.coordinator.processed_data(), self.description.slave, self.description.key, @@ -163,17 +163,17 @@ async def async_select_option(self, option: str) -> None: # TODO extract these type of property definitions to base class @property - def available(self) -> bool: + def available(self) -> Any: """Return True if entity available.""" full_key = str(self.description.slave) + "." + self.description.key return self.coordinator.processed_data()["availability"][full_key] @property - def device_info(self) -> entity.DeviceInfo: + def device_info(self) -> DeviceInfo: """Return the device info.""" - return entity.DeviceInfo( - identifiers={(DOMAIN, self.unique_id.split("_")[0])}, - name=self.unique_id.split("_")[1], - model=self.unique_id.split("_")[0], + return DeviceInfo( + identifiers={(DOMAIN, self.unique_id.split("_", maxsplit=1)[0])}, + name=self.unique_id.split("_", maxsplit=1)[1], + model=self.unique_id.split("_", maxsplit=1)[0], manufacturer="victron", ) diff --git a/custom_components/victron/sensor.py b/custom_components/victron/sensor.py index 7e8f584..0c11ba8 100644 --- a/custom_components/victron/sensor.py +++ b/custom_components/victron/sensor.py @@ -2,6 +2,7 @@ from dataclasses import dataclass import logging +from typing import Any from homeassistant.components.sensor import ( DOMAIN as SENSOR_DOMAIN, @@ -24,11 +25,10 @@ UnitOfVolume, ) from homeassistant.core import HassJob, HomeAssistant, callback -from homeassistant.helpers import entity +from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity -from .base import VictronBaseEntityDescription from .const import ( CONF_ADVANCED_OPTIONS, DOMAIN, @@ -37,7 +37,9 @@ TextReadEntityType, register_info_dict, ) -from .coordinator import victronEnergyDeviceUpdateCoordinator +from .coordinator import VictronEnergyDeviceUpdateCoordinator +from .entity import VictronBaseEntityDescription +from .select import VictronSelect _LOGGER = logging.getLogger(__name__) @@ -49,7 +51,7 @@ async def async_setup_entry( ) -> None: """Set up Victron energy sensor entries.""" _LOGGER.debug("attempting to setup sensor entities") - victron_coordinator: victronEnergyDeviceUpdateCoordinator = hass.data[DOMAIN][ + victron_coordinator: VictronEnergyDeviceUpdateCoordinator = hass.data[DOMAIN][ config_entry.entry_id ] _LOGGER.debug(victron_coordinator.processed_data()["register_set"]) @@ -61,18 +63,19 @@ async def async_setup_entry( for name in registerLedger: for register_name, registerInfo in register_info_dict[name].items(): _LOGGER.debug( - "unit == %s registerLedger == %s registerInfo", + "unit == %s registerLedger == %s register_info", slave, registerLedger, ) if config_entry.options[CONF_ADVANCED_OPTIONS]: if not isinstance( - registerInfo.entityType, ReadEntityType - ) or isinstance(registerInfo.entityType, BoolReadEntityType): + registerInfo.entity_type, ReadEntityType + ) or isinstance(registerInfo.entity_type, BoolReadEntityType): continue description = VictronEntityDescription( key=register_name, + translation_key=register_name, name=register_name.replace("_", " "), native_unit_of_measurement=registerInfo.unit, state_class=registerInfo.determine_stateclass(), @@ -80,25 +83,24 @@ async def async_setup_entry( device_class=determine_victron_device_class( register_name, registerInfo.unit ), - entity_type=registerInfo.entityType - if isinstance(registerInfo.entityType, TextReadEntityType) + entity_type=registerInfo.entity_type + if isinstance(registerInfo.entity_type, TextReadEntityType) else None, ) _LOGGER.debug("composed description == %s", description) descriptions.append(description) - entities = [] - entity = {} - for description in descriptions: - entity = description - entities.append(VictronSensor(victron_coordinator, entity)) + _entities = [ + VictronSelect(hass, victron_coordinator, description) + for description in descriptions + ] # Add an entity for each sensor type - async_add_entities(entities, True) + async_add_entities(_entities, True) -def determine_victron_device_class(name, unit): +def determine_victron_device_class(name: Any, unit: Any) -> Any: """Determine the device class of a sensor based on its name and unit.""" if unit == PERCENTAGE and "soc" in name: return SensorDeviceClass.BATTERY @@ -132,11 +134,11 @@ def determine_victron_device_class(name, unit): return None -@dataclass +@dataclass(frozen=True) class VictronEntityDescription(SensorEntityDescription, VictronBaseEntityDescription): """Describes victron sensor entity.""" - entity_type: ReadEntityType = None + entity_type: ReadEntityType | None = None class VictronSensor(CoordinatorEntity, SensorEntity): @@ -144,7 +146,7 @@ class VictronSensor(CoordinatorEntity, SensorEntity): def __init__( self, - coordinator: victronEnergyDeviceUpdateCoordinator, + coordinator: VictronEnergyDeviceUpdateCoordinator, description: VictronEntityDescription, ) -> None: """Initialize the sensor.""" @@ -173,7 +175,7 @@ def _handle_coordinator_update(self) -> None: """Get the latest data and updates the states.""" try: if self.available: - data = self.description.value_fn( + data = self.description.value_fn( # type: ignore[call-arg] self.coordinator.processed_data(), self.description.slave, self.description.key, @@ -181,8 +183,8 @@ def _handle_coordinator_update(self) -> None: if self.entity_type is not None and isinstance( self.entity_type, TextReadEntityType ): - if data in {item.value for item in self.entity_type.decodeEnum}: - self._attr_native_value = self.entity_type.decodeEnum( + if data in {item.value for item in self.entity_type.decode_enum}: + self._attr_native_value = self.entity_type.decode_enum( data ).name.split("_DUPLICATE")[0] else: @@ -199,20 +201,20 @@ def _handle_coordinator_update(self) -> None: except (TypeError, IndexError): _LOGGER.debug("failed to retrieve value") # No data available - self._attr_native_value = None + self._attr_native_value = "" @property - def available(self) -> bool: + def available(self) -> Any: """Return True if entity is available.""" full_key = str(self.description.slave) + "." + self.description.key return self.coordinator.processed_data()["availability"][full_key] @property - def device_info(self) -> entity.DeviceInfo: + def device_info(self) -> DeviceInfo: """Return the device info.""" - return entity.DeviceInfo( - identifiers={(DOMAIN, self.unique_id.split("_")[0])}, - name=self.unique_id.split("_")[1], - model=self.unique_id.split("_")[0], + return DeviceInfo( + identifiers={(DOMAIN, self.unique_id.split("_", maxsplit=1)[0])}, + name=self.unique_id.split("_", maxsplit=1)[1], + model=self.unique_id.split("_", maxsplit=1)[0], manufacturer="victron", # to be dynamically set for gavazzi and redflow ) diff --git a/custom_components/victron/strings.json b/custom_components/victron/strings.json index 1355ec9..b71c886 100644 --- a/custom_components/victron/strings.json +++ b/custom_components/victron/strings.json @@ -5,18 +5,18 @@ "data": { "host": "[%key:common::config_flow::data::host%]", "port": "[%key:common::config_flow::data::port%]", - "interval": "[%key:common::config_flow::data::interval%]", + "interval": "Interval", "advanced": "%key:common::config_flow::data::advanced%" } }, "advanced": { "data": { - "use_sliders": "[%key:common::config_flow::data::use_sliders%]", - "number_of_phases": "[%key:common::config_flow::data::number_of_phases%]", - "ac_voltage": "[%key:common::config_flow::data::ac_voltage%]", - "dc_voltage": "[%key:common::config_flow::data::dc_voltage%]", - "dc_current": "[%key:common::config_flow::data::ac_current%]", - "ac_current": "[%key:common::config_flow::data::dc_current%]" + "use_sliders": "Use sliders", + "number_of_phases": "Number of phases", + "ac_voltage": "AC Voltage", + "dc_voltage": "DC Voltage", + "dc_current": "DC current limit", + "ac_current": "AC current limit" } } }, @@ -28,5 +28,5 @@ "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" } - } + } } diff --git a/custom_components/victron/switch.py b/custom_components/victron/switch.py index 57def6c..bf83ac5 100644 --- a/custom_components/victron/switch.py +++ b/custom_components/victron/switch.py @@ -13,13 +13,14 @@ ) from homeassistant.config_entries import ConfigEntry from homeassistant.core import HassJob, HomeAssistant -from homeassistant.helpers import entity +from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity -from .base import VictronWriteBaseEntityDescription from .const import CONF_ADVANCED_OPTIONS, DOMAIN, SwitchWriteType, register_info_dict -from .coordinator import victronEnergyDeviceUpdateCoordinator +from .coordinator import VictronEnergyDeviceUpdateCoordinator +from .entity import VictronWriteBaseEntityDescription +from .select import VictronSelect _LOGGER = logging.getLogger(__name__) @@ -30,7 +31,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up victron switch devices.""" - victron_coordinator: victronEnergyDeviceUpdateCoordinator = hass.data[DOMAIN][ + victron_coordinator: VictronEnergyDeviceUpdateCoordinator = hass.data[DOMAIN][ config_entry.entry_id ] _LOGGER.debug("attempting to setup switch entities") @@ -42,13 +43,13 @@ async def async_setup_entry( for name in registerLedger: for register_name, registerInfo in register_info_dict[name].items(): _LOGGER.debug( - "unit == %s registerLedger == %s registerInfo == %s", + "unit == %s registerLedger == %s register_info == %s", slave, registerLedger, registerInfo, ) - if isinstance(registerInfo.entityType, SwitchWriteType): + if isinstance(registerInfo.entity_type, SwitchWriteType): description = VictronEntityDescription( key=register_name, name=register_name.replace("_", " "), @@ -58,19 +59,19 @@ async def async_setup_entry( descriptions.append(description) _LOGGER.debug("composed description == %s", description) - entities = [] - entity = {} - for description in descriptions: - entity = description - entities.append(VictronSwitch(hass, victron_coordinator, entity)) + _entities = [ + VictronSelect(hass, victron_coordinator, description) + for description in descriptions + ] _LOGGER.debug("adding switches") - _LOGGER.debug(entities) - async_add_entities(entities) + _LOGGER.debug(_entities) + async_add_entities(_entities) -@dataclass +@dataclass(frozen=True) class VictronEntityDescription( - SwitchEntityDescription, VictronWriteBaseEntityDescription + SwitchEntityDescription, + VictronWriteBaseEntityDescription, ): """Describes victron sensor entity.""" @@ -81,11 +82,10 @@ class VictronSwitch(CoordinatorEntity, SwitchEntity): def __init__( self, hass: HomeAssistant, - coordinator: victronEnergyDeviceUpdateCoordinator, + coordinator: VictronEnergyDeviceUpdateCoordinator, description: VictronEntityDescription, ) -> None: """Initialize the switch.""" - self.coordinator = coordinator self.description: VictronEntityDescription = description self._attr_name = f"{description.name}" self.data_key = str(self.description.slave) + "." + str(self.description.key) @@ -119,7 +119,7 @@ async def async_turn_off(self, **kwargs: Any) -> None: @property def is_on(self) -> bool: """Return true if switch is on.""" - data = self.description.value_fn( + data = self.description.value_fn( # type: ignore[call-arg] self.coordinator.processed_data(), self.description.slave, self.description.key, @@ -127,17 +127,17 @@ def is_on(self) -> bool: return cast("bool", data) @property - def available(self) -> bool: + def available(self) -> Any: """Return True if entity is available.""" full_key = str(self.description.slave) + "." + self.description.key return self.coordinator.processed_data()["availability"][full_key] @property - def device_info(self) -> entity.DeviceInfo: + def device_info(self) -> DeviceInfo: """Return the device info.""" - return entity.DeviceInfo( - identifiers={(DOMAIN, self.unique_id.split("_")[0])}, - name=self.unique_id.split("_")[1], - model=self.unique_id.split("_")[0], + return DeviceInfo( + identifiers={(DOMAIN, self.unique_id.split("_", maxsplit=1)[0])}, + name=self.unique_id.split("_", maxsplit=1)[1], + model=self.unique_id.split("_", maxsplit=1)[0], manufacturer="victron", ) diff --git a/custom_components/victron/translations/en.json b/custom_components/victron/translations/en.json index a5b0243..a1b897a 100644 --- a/custom_components/victron/translations/en.json +++ b/custom_components/victron/translations/en.json @@ -16,6 +16,12 @@ "port": "Port", "interval": "update interval in (s)", "advanced": "Enables write support and allows setting write limits" + }, + "data_description": { + "host": "The hostname or IP address of your Victron GX device.", + "port": "The port of your Victron GX device.", + "interval": "Polling interval.", + "advanced": "Advanced configuration." } }, "advanced": { diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 0000000..8482138 --- /dev/null +++ b/mypy.ini @@ -0,0 +1,5513 @@ +# Automatically generated by hassfest. +# +# To update, run python3 -m script.hassfest -p mypy_config + +[mypy] +python_version = 3.13 +platform = linux +plugins = pydantic.mypy, pydantic.v1.mypy +show_error_codes = true +follow_imports = normal +local_partial_types = true +strict_equality = true +strict_bytes = true +no_implicit_optional = true +warn_incomplete_stub = true +warn_redundant_casts = true +warn_unused_configs = true +warn_unused_ignores = true +enable_error_code = deprecated, ignore-without-code, redundant-self, truthy-iterable +disable_error_code = annotation-unchecked, import-not-found, import-untyped +extra_checks = false +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[pydantic-mypy] +init_forbid_extra = true +init_typed = true +warn_required_dynamic_aliases = true +warn_untyped_fields = true + +[mypy-homeassistant.*] +no_implicit_reexport = true + +[mypy-homeassistant.auth.auth_store] +disallow_any_generics = true + +[mypy-homeassistant.auth.providers.*] +disallow_any_generics = true + +[mypy-homeassistant.core] +disallow_any_generics = true + +[mypy-homeassistant.exceptions] +disallow_any_generics = true + +[mypy-homeassistant.helpers.area_registry] +disallow_any_generics = true + +[mypy-homeassistant.helpers.condition] +disallow_any_generics = true + +[mypy-homeassistant.helpers.debounce] +disallow_any_generics = true + +[mypy-homeassistant.helpers.deprecation] +disallow_any_generics = true + +[mypy-homeassistant.helpers.device_registry] +disallow_any_generics = true + +[mypy-homeassistant.helpers.discovery] +disallow_any_generics = true + +[mypy-homeassistant.helpers.dispatcher] +disallow_any_generics = true + +[mypy-homeassistant.helpers.entity] +disallow_any_generics = true + +[mypy-homeassistant.helpers.entity_platform] +disallow_any_generics = true + +[mypy-homeassistant.helpers.entity_values] +disallow_any_generics = true + +[mypy-homeassistant.helpers.event] +disallow_any_generics = true + +[mypy-homeassistant.helpers.reload] +disallow_any_generics = true + +[mypy-homeassistant.helpers.script] +disallow_any_generics = true + +[mypy-homeassistant.helpers.script_variables] +disallow_any_generics = true + +[mypy-homeassistant.helpers.singleton] +disallow_any_generics = true + +[mypy-homeassistant.helpers.sun] +disallow_any_generics = true + +[mypy-homeassistant.helpers.translation] +disallow_any_generics = true + +[mypy-homeassistant.loader] +disallow_any_generics = true + +[mypy-homeassistant.requirements] +disallow_any_generics = true + +[mypy-homeassistant.runner] +disallow_any_generics = true + +[mypy-homeassistant.setup] +disallow_any_generics = true + +[mypy-homeassistant.util.async_] +disallow_any_generics = true + +[mypy-homeassistant.util.color] +disallow_any_generics = true + +[mypy-homeassistant.util.decorator] +disallow_any_generics = true + +[mypy-homeassistant.util.location] +disallow_any_generics = true + +[mypy-homeassistant.util.logging] +disallow_any_generics = true + +[mypy-homeassistant.util.process] +disallow_any_generics = true + +[mypy-homeassistant.util.unit_system] +disallow_any_generics = true + +[mypy-homeassistant.components.*] +check_untyped_defs = false +disallow_incomplete_defs = false +disallow_subclassing_any = false +disallow_untyped_calls = false +disallow_untyped_decorators = false +disallow_untyped_defs = false +warn_return_any = false +warn_unreachable = false +no_implicit_reexport = false + +[mypy-homeassistant.components] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true +no_implicit_reexport = true + +[mypy-homeassistant.components.abode.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.acaia.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.accuweather.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.acer_projector.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.acmeda.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.actiontec.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.adax.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.adguard.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.aftership.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.air_quality.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.airgradient.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.airly.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.airnow.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.airos.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.airq.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.airthings.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.airthings_ble.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.airtouch5.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.airvisual.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.airvisual_pro.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.airzone.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.airzone_cloud.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.aladdin_connect.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.alarm_control_panel.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.alert.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.alexa.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.alexa_devices.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.alpha_vantage.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.altruist.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.amazon_polly.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.amberelectric.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.ambient_network.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.ambient_station.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.amcrest.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.ampio.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.analytics.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.analytics_insights.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.android_ip_webcam.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.androidtv.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.androidtv_remote.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.anel_pwrctrl.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.anova.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.anthemav.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.apache_kafka.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.apcupsd.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.api.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.apple_tv.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.apprise.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.aprs.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.apsystems.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.aqualogic.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.aquostv.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.aranet.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.arcam_fmj.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.arris_tg2492lg.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.aruba.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.arwn.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.aseko_pool_live.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.assist_pipeline.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.assist_satellite.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.asuswrt.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.autarco.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.auth.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.automation.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.awair.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.axis.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.azure_storage.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.backup.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.baf.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.bang_olufsen.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.bayesian.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.binary_sensor.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.bitcoin.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.blockchain.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.blue_current.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.blueprint.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.bluesound.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.bluetooth.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.bluetooth_adapters.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.bluetooth_tracker.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.bmw_connected_drive.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.bond.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.bosch_alarm.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.braviatv.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.bring.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.brother.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.browser.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.bryant_evolution.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.bthome.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.button.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.calendar.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.cambridge_audio.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.camera.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.canary.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.cert_expiry.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.clickatell.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.clicksend.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.climate.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.cloud.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.co2signal.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.comelit.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.command_line.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.config.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.configurator.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.cookidoo.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.counter.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.cover.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.cpuspeed.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.crownstone.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.date.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.datetime.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.deako.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.deconz.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.default_config.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.demo.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.derivative.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.device_automation.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.device_tracker.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.devolo_home_control.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.devolo_home_network.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.dhcp.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.diagnostics.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true +no_implicit_reexport = true + +[mypy-homeassistant.components.discovergy.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.dlna_dmr.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.dlna_dms.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.dnsip.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.doorbird.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.dormakaba_dkey.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.downloader.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.dsmr.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.duckdns.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.dunehd.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.duotecno.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.easyenergy.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.ecovacs.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.ecowitt.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.efergy.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.eheimdigital.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.electrasmart.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.electric_kiwi.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.elevenlabs.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.elgato.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.elkm1.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.emulated_hue.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.energenie_power_sockets.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.energy.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.energyzero.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.enigma2.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.enphase_envoy.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.eq3btsmart.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.esphome.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.event.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.evil_genius_labs.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.evohome.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.faa_delays.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.fan.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.fastdotcom.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.feedreader.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.file_upload.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.filesize.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.filter.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.fitbit.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.flexit_bacnet.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.flux_led.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.forecast_solar.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.fritz.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.fritzbox.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.fritzbox_callmonitor.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.fronius.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.frontend.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.fujitsu_fglair.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.fully_kiosk.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.fyta.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.generic_hygrostat.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.generic_thermostat.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.geo_location.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.geocaching.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.gios.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.glances.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.go2rtc.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.goalzero.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.google.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.google_assistant_sdk.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.google_cloud.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.google_drive.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.google_photos.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.google_sheets.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.govee_ble.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.gpsd.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.greeneye_monitor.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.group.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.guardian.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.habitica.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.hardkernel.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.hardware.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.heos.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.here_travel_time.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.history.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.history_stats.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.holiday.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.home_connect.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.homeassistant.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.homeassistant_alerts.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.homeassistant_green.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.homeassistant_hardware.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.homeassistant_sky_connect.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.homeassistant_yellow.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.homee.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.homekit.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.homekit_controller] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.homekit_controller.alarm_control_panel] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.homekit_controller.button] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.homekit_controller.config_flow] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.homekit_controller.const] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.homekit_controller.lock] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.homekit_controller.select] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.homekit_controller.storage] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.homekit_controller.utils] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.homewizard.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.homeworks.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.http.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.huawei_lte.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.humidifier.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.husqvarna_automower.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.hydrawise.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.hyperion.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.ibeacon.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.idasen_desk.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.image.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.image_processing.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.image_upload.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.imap.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.imgw_pib.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.immich.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.incomfort.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.input_button.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.input_select.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.input_text.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.integration.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.intent.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.intent_script.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.ios.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.iotty.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.ipp.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.iqvia.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.iron_os.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.islamic_prayer_times.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.isy994.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.jellyfin.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.jewish_calendar.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.jvc_projector.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.kaleidescape.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.knocki.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.knx.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.kraken.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.kulersky.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.lacrosse.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.lacrosse_view.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.lamarzocco.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.lametric.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.laundrify.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.lawn_mower.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.lcn.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.ld2410_ble.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.led_ble.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.lektrico.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.letpot.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.lidarr.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.lifx.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.light.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.linear_garage_door.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.linkplay.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.litejet.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.litterrobot.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.local_ip.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.local_todo.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.lock.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.logbook.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.logger.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.london_underground.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.lookin.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.lovelace.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.luftdaten.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.madvr.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.manual.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.mastodon.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.matrix.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.matter.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.mcp.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.mcp_server.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.mealie.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.media_extractor.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.media_player.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.media_source.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.met_eireann.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.metoffice.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.miele.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.mikrotik.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.min_max.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.minecraft_server.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.mjpeg.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.modbus.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.modem_callerid.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.mold_indicator.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.monzo.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.moon.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.mopeka.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.motionmount.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.mqtt.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.music_assistant.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.my.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.mysensors.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.myuplink.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.nam.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.nanoleaf.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.nasweb.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.neato.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.nest.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.netatmo.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.network.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.nextdns.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.nfandroidtv.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.nightscout.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.nissan_leaf.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.no_ip.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.nordpool.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.notify.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.notion.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.ntfy.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.number.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.nut.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.ohme.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.onboarding.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.oncue.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.onedrive.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.onewire.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.onkyo.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.open_meteo.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.open_router.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.openai_conversation.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.openexchangerates.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.opensky.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.openuv.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.opower.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.oralb.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.otbr.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.overkiz.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.overseerr.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.p1_monitor.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.pandora.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.panel_custom.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.paperless_ngx.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.peblar.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.peco.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.pegel_online.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.persistent_notification.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.person.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.pi_hole.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.ping.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.plugwise.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.powerfox.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.powerwall.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.private_ble_device.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.prometheus.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.proximity.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.prusalink.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.pure_energie.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.purpleair.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.pushbullet.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.pvoutput.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.pyload.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.python_script.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.qbus.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.qnap_qsw.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.rabbitair.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.radarr.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.radio_browser.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.rainforest_raven.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.rainmachine.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.raspberry_pi.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.rdw.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.recollect_waste.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.recorder.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.remember_the_milk.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.remote.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.remote_calendar.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.renault.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.reolink.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.repairs.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.rest.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.rest_command.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.rfxtrx.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.rhasspy.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.ridwell.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.ring.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.rituals_perfume_genie.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.roborock.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.roku.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.romy.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.rpi_power.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.rss_feed_template.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.russound_rio.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.ruuvi_gateway.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.ruuvitag_ble.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.samsungtv.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.scene.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.schedule.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.schlage.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.scrape.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.script.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.search.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.select.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.sensibo.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.sensirion_ble.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.sensor.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.sensorpush_cloud.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.sensoterra.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.senz.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.sfr_box.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.shell_command.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.shelly.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.shopping_list.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.simplepush.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.simplisafe.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.siren.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.skybell.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.slack.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.sleepiq.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.smhi.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.smlight.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.smtp.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.snooz.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.solarlog.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.sonarr.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.speedtestdotnet.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.spotify.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true +no_implicit_reexport = true + +[mypy-homeassistant.components.sql.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.squeezebox.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.ssdp.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.starlink.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.statistics.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.steamist.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.stookwijzer.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.stream.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true +no_implicit_reexport = true + +[mypy-homeassistant.components.streamlabswater.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.stt.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.suez_water.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.sun.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.surepetcare.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.switch.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.switch_as_x.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.switchbee.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.switchbot_cloud.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.switcher_kis.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.synology_dsm.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.system_health.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.system_log.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.systemmonitor.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.tag.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.tailscale.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.tailwind.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.tami4.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.tankerkoenig.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.tautulli.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.tcp.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.technove.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.tedee.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.telegram_bot.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.text.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.thethingsnetwork.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.threshold.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.tibber.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.tile.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.tilt_ble.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.time.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.time_date.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.timer.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.tod.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.todo.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.tolo.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.tplink.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.tplink_omada.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.trace.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.tractive.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.tradfri.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.trafikverket_camera.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.trafikverket_ferry.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.trafikverket_train.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.trafikverket_weatherstation.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.transmission.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.trend.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.tts.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.twentemilieu.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.unifi.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.unifiprotect.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.upcloud.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.update.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true +no_implicit_reexport = true + +[mypy-homeassistant.components.uptime.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.uptime_kuma.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.uptimerobot.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.usb.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.uvc.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.vacuum.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.vallox.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.valve.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.velbus.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.vlc_telnet.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.vodafone_station.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.volvo.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.wake_on_lan.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.wake_word.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.wallbox.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.waqi.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.water_heater.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.watttime.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.weather.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.webhook.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.webostv.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.websocket_api.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.wemo.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.whois.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.withings.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.wiz.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.wled.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.workday.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.worldclock.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.xiaomi_ble.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.yale_smart_alarm.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.yalexs_ble.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.youtube.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.zeroconf.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.zodiac.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.zone.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.zwave_js.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + +[mypy-homeassistant.components.application_credentials.*] +no_implicit_reexport = true + +[mypy-tests.*] +check_untyped_defs = false +disallow_incomplete_defs = false +disallow_subclassing_any = false +disallow_untyped_calls = false +disallow_untyped_decorators = false +disallow_untyped_defs = false +warn_return_any = false +warn_unreachable = false diff --git a/pyproject.toml b/pyproject.toml index c9a55ab..c286ba0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -609,4 +609,4 @@ split-on-trailing-comma = false max-complexity = 25 [tool.ruff.lint.pydocstyle] -property-decorators = ["propcache.api.cached_property"] +property-decorators = ["propcache.api.cached_property"] \ No newline at end of file diff --git a/ruff.toml b/ruff.toml index a137396..e738487 100644 --- a/ruff.toml +++ b/ruff.toml @@ -9,4 +9,4 @@ extend-ignore = [ [lint.isort] known-third-party = [ "pylint", -] +] \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..2390f14 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +"""Tests for the Victron GX modbusTCP integration.""" diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..0ee1388 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,44 @@ +"""Common fixtures for the Victron GX modbusTCP tests.""" + +from collections.abc import Generator +from unittest.mock import MagicMock, patch + +import pytest + +from homeassistant.components.victron import DOMAIN +from homeassistant.const import CONF_HOST, CONF_PORT + +from tests.common import MockConfigEntry + + +@pytest.fixture +def mock_victron_client() -> Generator[MagicMock]: + """Mock a victron client.""" + with ( + patch( + "homeassistant.components.victron.config_flow.ModbusTcpClient", + ) as mock_client, + ): + client = mock_client.return_value + client.update.return_value = True + yield client + + +@pytest.fixture(autouse=True) +def mock_modbus() -> Generator[MagicMock]: + """Mock a modbus client.""" + with patch( + "homeassistant.components.victron.config_flow.ModbusTcpClient", + autospec=True, + ) as mock_client: + yield mock_client + + +@pytest.fixture +def mock_config_entry() -> MockConfigEntry: + """Mock a config entry.""" + return MockConfigEntry( + domain=DOMAIN, + title="victron", + data={CONF_HOST: "1.1.1.1", CONF_PORT: 502}, + ) diff --git a/tests/test_config_flow.py b/tests/test_config_flow.py new file mode 100644 index 0000000..deb98f0 --- /dev/null +++ b/tests/test_config_flow.py @@ -0,0 +1,128 @@ +"""Test the Victron GX modbusTCP config flow.""" + +from unittest.mock import AsyncMock, patch + +import pytest + +from homeassistant import config_entries +from homeassistant.components.victron.config_flow import CannotConnect, InvalidAuth +from homeassistant.components.victron.const import ( + CONF_ADVANCED_OPTIONS, + CONF_INTERVAL, + DOMAIN, +) +from homeassistant.config_entries import SOURCE_USER +from homeassistant.const import CONF_HOST, CONF_PORT +from homeassistant.core import HomeAssistant +from homeassistant.data_entry_flow import FlowResultType +from homeassistant.exceptions import HomeAssistantError + + +@pytest.mark.usefixtures("mock_victron_client") +async def test_full_flow(hass: HomeAssistant) -> None: + """Test the full flow.""" + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": SOURCE_USER} + ) + assert result["type"] is FlowResultType.FORM + assert not result["errors"] + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + CONF_HOST: "1.1.1.1", + CONF_PORT: 502, + CONF_INTERVAL: 30, + CONF_ADVANCED_OPTIONS: False, + }, + ) + + assert result["type"] is FlowResultType.CREATE_ENTRY + assert result["title"] == "victron" + assert result["options"] == { + CONF_HOST: "1.1.1.1", + CONF_PORT: 502, + CONF_INTERVAL: 30, + CONF_ADVANCED_OPTIONS: False, + } + + +@pytest.mark.usefixtures("mock_victron_client") +async def test_form_cannot_connect(hass: HomeAssistant) -> None: + """Test we handle cannot connect error.""" + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_USER} + ) + with patch( + "homeassistant.components.victron.config_flow.validate_input", + new=AsyncMock(side_effect=CannotConnect), + ) as mock_get: + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + CONF_HOST: "1.1.1.1", + CONF_PORT: 502, + CONF_INTERVAL: 30, + CONF_ADVANCED_OPTIONS: False, + }, + ) + mock_get.assert_called_once() + + assert result2["type"] is FlowResultType.FORM + assert result2["step_id"] == "user" + assert result2["errors"] == {"base": "cannot_connect"} + + +@pytest.mark.usefixtures("mock_victron_client") +async def test_form_invalid_auth(hass: HomeAssistant) -> None: + """Test we handle cannot connect error.""" + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_USER} + ) + with patch( + "homeassistant.components.victron.config_flow.validate_input", + new=AsyncMock(side_effect=InvalidAuth), + ) as mock_get: + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + CONF_HOST: "1.1.1.1", + CONF_PORT: 502, + CONF_INTERVAL: 30, + CONF_ADVANCED_OPTIONS: False, + }, + ) + mock_get.assert_called_once() + + assert result2["type"] is FlowResultType.FORM + assert result2["step_id"] == "user" + assert result2["errors"] == {"base": "invalid_auth"} + + +@pytest.mark.usefixtures("mock_victron_client") +async def test_form_unknown_exception(hass: HomeAssistant) -> None: + """Test we handle cannot connect error.""" + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_USER} + ) + with patch( + "homeassistant.components.victron.config_flow.validate_input", + new=AsyncMock(side_effect=HomeAssistantError), + ) as mock_get: + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + CONF_HOST: "1.1.1.1", + CONF_PORT: 502, + CONF_INTERVAL: 30, + CONF_ADVANCED_OPTIONS: False, + }, + ) + mock_get.assert_called_once() + + assert result2["type"] is FlowResultType.FORM + assert result2["step_id"] == "user" + assert result2["errors"] == {"base": "unknown"}