108 lines
3.3 KiB
Python
108 lines
3.3 KiB
Python
"""Support for Node-RED discovery."""
|
|
import asyncio
|
|
import logging
|
|
|
|
from homeassistant.helpers.dispatcher import (
|
|
async_dispatcher_connect,
|
|
async_dispatcher_send,
|
|
)
|
|
from homeassistant.helpers.typing import HomeAssistantType
|
|
|
|
from .const import (
|
|
CONF_BINARY_SENSOR,
|
|
CONF_COMPONENT,
|
|
CONF_NODE_ID,
|
|
CONF_REMOVE,
|
|
CONF_SENSOR,
|
|
CONF_SERVER_ID,
|
|
CONF_SWITCH,
|
|
DOMAIN,
|
|
DOMAIN_DATA,
|
|
NODERED_DISCOVERY,
|
|
NODERED_DISCOVERY_NEW,
|
|
NODERED_DISCOVERY_UPDATED,
|
|
)
|
|
|
|
SUPPORTED_COMPONENTS = [
|
|
CONF_SWITCH,
|
|
CONF_BINARY_SENSOR,
|
|
CONF_SENSOR,
|
|
]
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
ALREADY_DISCOVERED = "discovered_components"
|
|
CHANGE_ENTITY_TYPE = "change_entity_type"
|
|
CONFIG_ENTRY_LOCK = "config_entry_lock"
|
|
CONFIG_ENTRY_IS_SETUP = "config_entry_is_setup"
|
|
DISCOVERY_DISPATCHED = "discovery_dispatched"
|
|
|
|
|
|
async def start_discovery(
|
|
hass: HomeAssistantType, hass_config, config_entry=None
|
|
) -> bool:
|
|
"""Initialize of Node-RED Discovery."""
|
|
|
|
async def async_device_message_received(msg, connection):
|
|
"""Process the received message."""
|
|
component = msg[CONF_COMPONENT]
|
|
server_id = msg[CONF_SERVER_ID]
|
|
node_id = msg[CONF_NODE_ID]
|
|
|
|
if component not in SUPPORTED_COMPONENTS:
|
|
_LOGGER.warning(f"Integration {component} is not supported")
|
|
return
|
|
|
|
discovery_hash = f"{DOMAIN}-{server_id}-{node_id}"
|
|
data = hass.data[DOMAIN_DATA]
|
|
|
|
_LOGGER.debug(f"Discovery message: {msg}")
|
|
|
|
if ALREADY_DISCOVERED not in data:
|
|
data[ALREADY_DISCOVERED] = {}
|
|
if discovery_hash in data[ALREADY_DISCOVERED]:
|
|
|
|
if data[ALREADY_DISCOVERED][discovery_hash] != component:
|
|
# Remove old
|
|
log_text = f"Changing {data[ALREADY_DISCOVERED][discovery_hash]} to"
|
|
msg[CONF_REMOVE] = CHANGE_ENTITY_TYPE
|
|
elif CONF_REMOVE in msg:
|
|
log_text = "Removing"
|
|
else:
|
|
# Dispatch update
|
|
log_text = "Updating"
|
|
|
|
_LOGGER.info(f"{log_text} {component} {server_id} {node_id}")
|
|
|
|
data[ALREADY_DISCOVERED][discovery_hash] = component
|
|
async_dispatcher_send(
|
|
hass, NODERED_DISCOVERY_UPDATED.format(discovery_hash), msg, connection
|
|
)
|
|
else:
|
|
# Add component
|
|
_LOGGER.info(f"Creating {component} {server_id} {node_id}")
|
|
data[ALREADY_DISCOVERED][discovery_hash] = component
|
|
|
|
async with data[CONFIG_ENTRY_LOCK]:
|
|
if component not in data[CONFIG_ENTRY_IS_SETUP]:
|
|
await hass.config_entries.async_forward_entry_setup(
|
|
config_entry, component
|
|
)
|
|
data[CONFIG_ENTRY_IS_SETUP].add(component)
|
|
|
|
async_dispatcher_send(
|
|
hass, NODERED_DISCOVERY_NEW.format(component), msg, connection
|
|
)
|
|
|
|
hass.data[DOMAIN_DATA][CONFIG_ENTRY_LOCK] = asyncio.Lock()
|
|
hass.data[DOMAIN_DATA][CONFIG_ENTRY_IS_SETUP] = set()
|
|
|
|
hass.data[DOMAIN_DATA][DISCOVERY_DISPATCHED] = async_dispatcher_connect(
|
|
hass, NODERED_DISCOVERY, async_device_message_received,
|
|
)
|
|
|
|
|
|
def stop_discovery(hass: HomeAssistantType):
|
|
"""Remove discovery dispatcher."""
|
|
hass.data[DOMAIN_DATA][DISCOVERY_DISPATCHED]()
|