1
mirror of https://github.com/home-assistant/core synced 2024-09-03 08:14:07 +02:00
ha-core/homeassistant/components/ihc/auto_setup.py
Jens Østergaard Nielsen a644baf3cd
Prepare for Ihc config flow (#64852)
* Extracting group and extra  info from ihc products

* Make suggested area not optional

* Revert back to assignment expression :=

* Make auto setup show device info for all platforms

* Change code comment to #

* Add return typing

* Remove device_info key without value

* get_manual_configuration typings for everything

* Adding IHCController typings

* Remove "ihc" from unique id

* Remove device_info

* Separator in unique id

* Return typing on ihc_setup

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* Update homeassistant/components/ihc/ihcdevice.py

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* Update homeassistant/components/ihc/ihcdevice.py

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* Raise ValueError instead of logging an error

* Update homeassistant/components/ihc/service_functions.py

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* Catch up with dev

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2022-02-11 10:24:31 +01:00

147 lines
5.1 KiB
Python

"""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:
product_id = int(product.attrib["id"].strip("_"), 0)
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}"
# make the model number look a bit nicer - strip leading _
model = product.get("product_identifier", "").lstrip("_")
device = {
"ihc_id": ihc_id,
"ctrl_id": controller_id,
"product": {
"id": product_id,
"name": product.get("name") or "",
"note": product.get("note") or "",
"position": product.get("position") or "",
"model": model,
"group": groupname,
},
"product_cfg": product_cfg,
}
discovery_data[name] = device
return discovery_data