diff --git a/.coveragerc b/.coveragerc index 2f6e7a9adf8..26b6413b4c0 100644 --- a/.coveragerc +++ b/.coveragerc @@ -65,6 +65,8 @@ omit = homeassistant/components/scsgate.py homeassistant/components/*/scsgate.py + homeassistant/components/upnp.py + homeassistant/components/binary_sensor/arest.py homeassistant/components/binary_sensor/rest.py homeassistant/components/browser.py diff --git a/homeassistant/components/upnp.py b/homeassistant/components/upnp.py new file mode 100644 index 00000000000..0a2c02666e2 --- /dev/null +++ b/homeassistant/components/upnp.py @@ -0,0 +1,45 @@ +""" +This module will attempt to open a port in your router for Home Assistant. + +For more details about UPnP, please refer to the documentation at +https://home-assistant.io/components/upnp/ +""" +import logging + +from homeassistant.const import (EVENT_HOMEASSISTANT_STOP) + +DEPENDENCIES = ["api"] + +_LOGGER = logging.getLogger(__name__) + +DOMAIN = "upnp" + + +def setup(hass, config): + """Register a port mapping for Home Assistant via UPnP.""" + import miniupnpc + + # Miniupnpc dynamically includes UPnP + # pylint: disable=no-name-in-module, no-member + upnp = miniupnpc.UPnP() + + upnp.discoverdelay = 200 + upnp.discover() + try: + upnp.selectigd() + # pylint: disable=broad-except + except Exception: + _LOGGER.exception("Error when attempting to discover a UPnP IGD") + return False + + upnp.addportmapping(hass.config.api.port, "TCP", + hass.config.api.host, hass.config.api.port, + "Home Assistant", "") + + def deregister_port(event): + """De-register the UPnP port mapping.""" + upnp.deleteportmapping(hass.config.api.port, "TCP") + + hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, deregister_port) + + return True