Move autosetup out of init.py (#64761)

This commit is contained in:
Jens Østergaard Nielsen 2022-01-24 12:07:54 +01:00 committed by GitHub
parent a5eac99208
commit 1ffc2a05db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 152 additions and 127 deletions

View File

@ -1,13 +1,10 @@
"""Support for IHC devices.""" """Support for IHC devices."""
import logging import logging
import os.path
from defusedxml import ElementTree
from ihcsdk.ihccontroller import IHCController from ihcsdk.ihccontroller import IHCController
import voluptuous as vol import voluptuous as vol
from homeassistant.components.binary_sensor import DEVICE_CLASSES_SCHEMA from homeassistant.components.binary_sensor import DEVICE_CLASSES_SCHEMA
from homeassistant.config import load_yaml_config_file
from homeassistant.const import ( from homeassistant.const import (
CONF_ID, CONF_ID,
CONF_NAME, CONF_NAME,
@ -17,13 +14,13 @@ from homeassistant.const import (
CONF_URL, CONF_URL,
CONF_USERNAME, CONF_USERNAME,
TEMP_CELSIUS, TEMP_CELSIUS,
Platform,
) )
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import discovery from homeassistant.helpers import discovery
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from .auto_setup import autosetup_ihc_products
from .const import ( from .const import (
CONF_AUTOSETUP, CONF_AUTOSETUP,
CONF_BINARY_SENSOR, CONF_BINARY_SENSOR,
@ -31,30 +28,21 @@ from .const import (
CONF_INFO, CONF_INFO,
CONF_INVERTING, CONF_INVERTING,
CONF_LIGHT, CONF_LIGHT,
CONF_NODE,
CONF_NOTE, CONF_NOTE,
CONF_OFF_ID, CONF_OFF_ID,
CONF_ON_ID, CONF_ON_ID,
CONF_POSITION, CONF_POSITION,
CONF_SENSOR, CONF_SENSOR,
CONF_SWITCH, CONF_SWITCH,
CONF_XPATH,
DOMAIN, DOMAIN,
IHC_CONTROLLER, IHC_CONTROLLER,
IHC_PLATFORMS,
) )
from .service_functions import setup_service_functions from .service_functions import setup_service_functions
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
AUTO_SETUP_YAML = "ihc_auto_setup.yaml"
IHC_INFO = "info" IHC_INFO = "info"
PLATFORMS = (
Platform.BINARY_SENSOR,
Platform.LIGHT,
Platform.SENSOR,
Platform.SWITCH,
)
def validate_name(config): def validate_name(config):
@ -130,62 +118,6 @@ CONFIG_SCHEMA = vol.Schema(
) )
AUTO_SETUP_SCHEMA = vol.Schema(
{
vol.Optional(CONF_BINARY_SENSOR, default=[]): vol.All(
cv.ensure_list,
[
vol.All(
{
vol.Required(CONF_NODE): cv.string,
vol.Required(CONF_XPATH): cv.string,
vol.Optional(CONF_INVERTING, default=False): cv.boolean,
vol.Optional(CONF_TYPE): cv.string,
}
)
],
),
vol.Optional(CONF_LIGHT, default=[]): vol.All(
cv.ensure_list,
[
vol.All(
{
vol.Required(CONF_NODE): cv.string,
vol.Required(CONF_XPATH): cv.string,
vol.Optional(CONF_DIMMABLE, default=False): cv.boolean,
}
)
],
),
vol.Optional(CONF_SENSOR, default=[]): vol.All(
cv.ensure_list,
[
vol.All(
{
vol.Required(CONF_NODE): cv.string,
vol.Required(CONF_XPATH): cv.string,
vol.Optional(
CONF_UNIT_OF_MEASUREMENT, default=TEMP_CELSIUS
): cv.string,
}
)
],
),
vol.Optional(CONF_SWITCH, default=[]): vol.All(
cv.ensure_list,
[
vol.All(
{
vol.Required(CONF_NODE): cv.string,
vol.Required(CONF_XPATH): cv.string,
}
)
],
),
}
)
def setup(hass: HomeAssistant, config: ConfigType) -> bool: def setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the IHC integration.""" """Set up the IHC integration."""
conf = config[DOMAIN] conf = config[DOMAIN]
@ -224,7 +156,7 @@ def ihc_setup(hass, config, conf, controller_id):
def get_manual_configuration(hass, config, conf, ihc_controller, controller_id): def get_manual_configuration(hass, config, conf, ihc_controller, controller_id):
"""Get manual configuration for IHC devices.""" """Get manual configuration for IHC devices."""
for platform in PLATFORMS: for platform in IHC_PLATFORMS:
discovery_info = {} discovery_info = {}
if platform in conf: if platform in conf:
platform_setup = conf.get(platform) platform_setup = conf.get(platform)
@ -250,59 +182,3 @@ def get_manual_configuration(hass, config, conf, ihc_controller, controller_id):
discovery_info[name] = device discovery_info[name] = device
if discovery_info: if discovery_info:
discovery.load_platform(hass, platform, DOMAIN, discovery_info, config) discovery.load_platform(hass, platform, DOMAIN, discovery_info, config)
def autosetup_ihc_products(hass: HomeAssistant, config, ihc_controller, controller_id):
"""Auto setup of IHC products from the IHC project file."""
if not (project_xml := ihc_controller.get_project()):
_LOGGER.error("Unable to read project from IHC controller")
return False
project = ElementTree.fromstring(project_xml)
# If an auto setup file exist in the configuration it will override
yaml_path = hass.config.path(AUTO_SETUP_YAML)
if not os.path.isfile(yaml_path):
yaml_path = os.path.join(os.path.dirname(__file__), AUTO_SETUP_YAML)
yaml = load_yaml_config_file(yaml_path)
try:
auto_setup_conf = AUTO_SETUP_SCHEMA(yaml)
except vol.Invalid as exception:
_LOGGER.error("Invalid IHC auto setup data: %s", exception)
return False
groups = project.findall(".//group")
for platform in PLATFORMS:
platform_setup = auto_setup_conf[platform]
discovery_info = get_discovery_info(platform_setup, groups, controller_id)
if discovery_info:
discovery.load_platform(hass, platform, DOMAIN, discovery_info, config)
return True
def get_discovery_info(platform_setup, groups, controller_id):
"""Get discovery info for specified IHC platform."""
discovery_data = {}
for group in groups:
groupname = group.attrib["name"]
for product_cfg in platform_setup:
products = group.findall(product_cfg[CONF_XPATH])
for product in products:
nodes = product.findall(product_cfg[CONF_NODE])
for node in nodes:
if "setting" in node.attrib and node.attrib["setting"] == "yes":
continue
ihc_id = int(node.attrib["id"].strip("_"), 0)
name = f"{groupname}_{ihc_id}"
device = {
"ihc_id": ihc_id,
"ctrl_id": controller_id,
"product": {
"name": product.get("name") or "",
"note": product.get("note") or "",
"position": product.get("position") or "",
},
"product_cfg": product_cfg,
}
discovery_data[name] = device
return discovery_data

View File

@ -0,0 +1,140 @@
"""Handle auto setup of IHC products from the ihc project file."""
import logging
import os.path
from defusedxml import ElementTree
import voluptuous as vol
from homeassistant.config import load_yaml_config_file
from homeassistant.const import CONF_TYPE, CONF_UNIT_OF_MEASUREMENT, TEMP_CELSIUS
from homeassistant.core import HomeAssistant
from homeassistant.helpers import discovery
import homeassistant.helpers.config_validation as cv
from .const import (
AUTO_SETUP_YAML,
CONF_BINARY_SENSOR,
CONF_DIMMABLE,
CONF_INVERTING,
CONF_LIGHT,
CONF_NODE,
CONF_SENSOR,
CONF_SWITCH,
CONF_XPATH,
DOMAIN,
IHC_PLATFORMS,
)
_LOGGER = logging.getLogger(__name__)
AUTO_SETUP_SCHEMA = vol.Schema(
{
vol.Optional(CONF_BINARY_SENSOR, default=[]): vol.All(
cv.ensure_list,
[
vol.All(
{
vol.Required(CONF_NODE): cv.string,
vol.Required(CONF_XPATH): cv.string,
vol.Optional(CONF_INVERTING, default=False): cv.boolean,
vol.Optional(CONF_TYPE): cv.string,
}
)
],
),
vol.Optional(CONF_LIGHT, default=[]): vol.All(
cv.ensure_list,
[
vol.All(
{
vol.Required(CONF_NODE): cv.string,
vol.Required(CONF_XPATH): cv.string,
vol.Optional(CONF_DIMMABLE, default=False): cv.boolean,
}
)
],
),
vol.Optional(CONF_SENSOR, default=[]): vol.All(
cv.ensure_list,
[
vol.All(
{
vol.Required(CONF_NODE): cv.string,
vol.Required(CONF_XPATH): cv.string,
vol.Optional(
CONF_UNIT_OF_MEASUREMENT, default=TEMP_CELSIUS
): cv.string,
}
)
],
),
vol.Optional(CONF_SWITCH, default=[]): vol.All(
cv.ensure_list,
[
vol.All(
{
vol.Required(CONF_NODE): cv.string,
vol.Required(CONF_XPATH): cv.string,
}
)
],
),
}
)
def autosetup_ihc_products(hass: HomeAssistant, config, ihc_controller, controller_id):
"""Auto setup of IHC products from the IHC project file."""
if not (project_xml := ihc_controller.get_project()):
_LOGGER.error("Unable to read project from IHC controller")
return False
project = ElementTree.fromstring(project_xml)
# If an auto setup file exist in the configuration it will override
yaml_path = hass.config.path(AUTO_SETUP_YAML)
if not os.path.isfile(yaml_path):
yaml_path = os.path.join(os.path.dirname(__file__), AUTO_SETUP_YAML)
yaml = load_yaml_config_file(yaml_path)
try:
auto_setup_conf = AUTO_SETUP_SCHEMA(yaml)
except vol.Invalid as exception:
_LOGGER.error("Invalid IHC auto setup data: %s", exception)
return False
groups = project.findall(".//group")
for platform in IHC_PLATFORMS:
platform_setup = auto_setup_conf[platform]
discovery_info = get_discovery_info(platform_setup, groups, controller_id)
if discovery_info:
discovery.load_platform(hass, platform, DOMAIN, discovery_info, config)
return True
def get_discovery_info(platform_setup, groups, controller_id):
"""Get discovery info for specified IHC platform."""
discovery_data = {}
for group in groups:
groupname = group.attrib["name"]
for product_cfg in platform_setup:
products = group.findall(product_cfg[CONF_XPATH])
for product in products:
nodes = product.findall(product_cfg[CONF_NODE])
for node in nodes:
if "setting" in node.attrib and node.attrib["setting"] == "yes":
continue
ihc_id = int(node.attrib["id"].strip("_"), 0)
name = f"{groupname}_{ihc_id}"
device = {
"ihc_id": ihc_id,
"ctrl_id": controller_id,
"product": {
"name": product.get("name") or "",
"note": product.get("note") or "",
"position": product.get("position") or "",
},
"product_cfg": product_cfg,
}
discovery_data[name] = device
return discovery_data

View File

@ -1,9 +1,12 @@
"""IHC component constants.""" """IHC component constants."""
from homeassistant.const import Platform
ATTR_IHC_ID = "ihc_id" ATTR_IHC_ID = "ihc_id"
ATTR_VALUE = "value" ATTR_VALUE = "value"
ATTR_CONTROLLER_ID = "controller_id" ATTR_CONTROLLER_ID = "controller_id"
AUTO_SETUP_YAML = "ihc_auto_setup.yaml"
CONF_AUTOSETUP = "auto_setup" CONF_AUTOSETUP = "auto_setup"
CONF_BINARY_SENSOR = "binary_sensor" CONF_BINARY_SENSOR = "binary_sensor"
CONF_DIMMABLE = "dimmable" CONF_DIMMABLE = "dimmable"
@ -22,6 +25,12 @@ CONF_XPATH = "xpath"
DOMAIN = "ihc" DOMAIN = "ihc"
IHC_CONTROLLER = "controller" IHC_CONTROLLER = "controller"
IHC_PLATFORMS = (
Platform.BINARY_SENSOR,
Platform.LIGHT,
Platform.SENSOR,
Platform.SWITCH,
)
SERVICE_SET_RUNTIME_VALUE_BOOL = "set_runtime_value_bool" SERVICE_SET_RUNTIME_VALUE_BOOL = "set_runtime_value_bool"
SERVICE_SET_RUNTIME_VALUE_FLOAT = "set_runtime_value_float" SERVICE_SET_RUNTIME_VALUE_FLOAT = "set_runtime_value_float"