From 8e17bf43e0e1e136845b74bf451288b197b0a4f3 Mon Sep 17 00:00:00 2001 From: Bryce Edwards Date: Tue, 17 Jan 2017 00:52:21 -0600 Subject: [PATCH] added upnp_bind_multicast option to emulated_hue component (#5381) --- homeassistant/components/emulated_hue/__init__.py | 11 ++++++++++- homeassistant/components/emulated_hue/upnp.py | 8 ++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/emulated_hue/__init__.py b/homeassistant/components/emulated_hue/__init__.py index 2efce06528d..d412a7af91f 100644 --- a/homeassistant/components/emulated_hue/__init__.py +++ b/homeassistant/components/emulated_hue/__init__.py @@ -26,6 +26,7 @@ _LOGGER = logging.getLogger(__name__) CONF_HOST_IP = 'host_ip' CONF_LISTEN_PORT = 'listen_port' +CONF_UPNP_BIND_MULTICAST = 'upnp_bind_multicast' CONF_OFF_MAPS_TO_ON_DOMAINS = 'off_maps_to_on_domains' CONF_EXPOSE_BY_DEFAULT = 'expose_by_default' CONF_EXPOSED_DOMAINS = 'exposed_domains' @@ -35,6 +36,7 @@ TYPE_ALEXA = 'alexa' TYPE_GOOGLE = 'google_home' DEFAULT_LISTEN_PORT = 8300 +DEFAULT_UPNP_BIND_MULTICAST = True DEFAULT_OFF_MAPS_TO_ON_DOMAINS = ['script', 'scene'] DEFAULT_EXPOSE_BY_DEFAULT = True DEFAULT_EXPOSED_DOMAINS = [ @@ -47,6 +49,7 @@ CONFIG_SCHEMA = vol.Schema({ vol.Optional(CONF_HOST_IP): cv.string, vol.Optional(CONF_LISTEN_PORT, default=DEFAULT_LISTEN_PORT): vol.All(vol.Coerce(int), vol.Range(min=1, max=65535)), + vol.Optional(CONF_UPNP_BIND_MULTICAST): cv.boolean, vol.Optional(CONF_OFF_MAPS_TO_ON_DOMAINS): cv.ensure_list, vol.Optional(CONF_EXPOSE_BY_DEFAULT): cv.boolean, vol.Optional(CONF_EXPOSED_DOMAINS): cv.ensure_list, @@ -84,7 +87,8 @@ def setup(hass, yaml_config): server.register_view(HueOneLightChangeView(config)) upnp_listener = UPNPResponderThread( - config.host_ip_addr, config.listen_port) + config.host_ip_addr, config.listen_port, + config.upnp_bind_multicast) @asyncio.coroutine def stop_emulated_hue_bridge(event): @@ -134,6 +138,11 @@ class Config(object): _LOGGER.warning('When targetting Google Home, listening port has ' 'to be port 80') + # Get whether or not UPNP binds to multicast address (239.255.255.250) + # or to the unicast address (host_ip_addr) + self.upnp_bind_multicast = conf.get( + CONF_UPNP_BIND_MULTICAST, DEFAULT_UPNP_BIND_MULTICAST) + # Get domains that cause both "on" and "off" commands to map to "on" # This is primarily useful for things like scenes or scripts, which # don't really have a concept of being off diff --git a/homeassistant/components/emulated_hue/upnp.py b/homeassistant/components/emulated_hue/upnp.py index fd880c40e6e..de3be34e2de 100644 --- a/homeassistant/components/emulated_hue/upnp.py +++ b/homeassistant/components/emulated_hue/upnp.py @@ -60,12 +60,13 @@ class UPNPResponderThread(threading.Thread): _interrupted = False - def __init__(self, host_ip_addr, listen_port): + def __init__(self, host_ip_addr, listen_port, upnp_bind_multicast): """Initialize the class.""" threading.Thread.__init__(self) self.host_ip_addr = host_ip_addr self.listen_port = listen_port + self.upnp_bind_multicast = upnp_bind_multicast # Note that the double newline at the end of # this string is required per the SSDP spec @@ -116,7 +117,10 @@ USN: uuid:Socket-1_0-221438K0100073::urn:schemas-upnp-org:device:basic:1 socket.inet_aton("239.255.255.250") + socket.inet_aton(self.host_ip_addr)) - ssdp_socket.bind(("239.255.255.250", 1900)) + if self.upnp_bind_multicast: + ssdp_socket.bind(("239.255.255.250", 1900)) + else: + ssdp_socket.bind((self.host_ip_addr, 1900)) while True: if self._interrupted: