Home Assistant Unofficial Reference 2024.12.1
gateway.py
Go to the documentation of this file.
1 """Code to handle a Motion Gateway."""
2 
3 import contextlib
4 import logging
5 import socket
6 
7 from motionblinds import DEVICE_TYPES_WIFI, AsyncMotionMulticast, MotionGateway
8 
9 from homeassistant.components import network
10 
11 from .const import DEFAULT_INTERFACE
12 
13 _LOGGER = logging.getLogger(__name__)
14 
15 
16 def device_name(blind):
17  """Construct common name part of a device."""
18  if blind.device_type in DEVICE_TYPES_WIFI:
19  return blind.blind_type
20  return f"{blind.blind_type} {blind.mac[12:]}"
21 
22 
24  """Class to async connect to a Motion Gateway."""
25 
26  def __init__(self, hass, multicast=None, interface=None):
27  """Initialize the entity."""
28  self._hass_hass = hass
29  self._multicast_multicast = multicast
30  self._gateway_device_gateway_device = None
31  self._interface_interface = interface
32 
33  @property
34  def gateway_device(self):
35  """Return the class containing all connections to the gateway."""
36  return self._gateway_device_gateway_device
37 
38  def update_gateway(self):
39  """Update all information of the gateway."""
40  self.gateway_devicegateway_device.GetDeviceList()
41  self.gateway_devicegateway_device.Update()
42  for blind in self.gateway_devicegateway_device.device_list.values():
43  blind.Update_from_cache()
44 
45  async def async_connect_gateway(self, host, key):
46  """Connect to the Motion Gateway."""
47  _LOGGER.debug("Initializing with host %s (key %s)", host, key[:3])
48  self._gateway_device_gateway_device = MotionGateway(
49  ip=host, key=key, multicast=self._multicast_multicast
50  )
51  try:
52  # update device info and get the connected sub devices
53  await self._hass_hass.async_add_executor_job(self.update_gatewayupdate_gateway)
54  except TimeoutError:
55  _LOGGER.error(
56  "Timeout trying to connect to Motion Gateway with host %s", host
57  )
58  return False
59  _LOGGER.debug(
60  "Motion gateway mac: %s, protocol: %s detected",
61  self.gateway_devicegateway_device.mac,
62  self.gateway_devicegateway_device.protocol,
63  )
64  return True
65 
66  def check_interface(self):
67  """Check if the current interface supports multicast."""
68  with contextlib.suppress(socket.timeout):
69  return self.gateway_devicegateway_device.Check_gateway_multicast()
70  return False
71 
72  async def async_get_interfaces(self):
73  """Get list of interface to use."""
74  interfaces = [DEFAULT_INTERFACE, "0.0.0.0"]
75  enabled_interfaces = []
76  default_interface = DEFAULT_INTERFACE
77 
78  adapters = await network.async_get_adapters(self._hass_hass)
79  for adapter in adapters:
80  if ipv4s := adapter["ipv4"]:
81  ip4 = ipv4s[0]["address"]
82  interfaces.append(ip4)
83  if adapter["enabled"]:
84  enabled_interfaces.append(ip4)
85  if adapter["default"]:
86  default_interface = ip4
87 
88  if len(enabled_interfaces) == 1:
89  default_interface = enabled_interfaces[0]
90  interfaces.remove(default_interface)
91  interfaces.insert(0, default_interface)
92 
93  if self._interface_interface is not None:
94  interfaces.remove(self._interface_interface)
95  interfaces.insert(0, self._interface_interface)
96 
97  return interfaces
98 
99  async def async_check_interface(self, host, key):
100  """Connect to the Motion Gateway."""
101  interfaces = await self.async_get_interfacesasync_get_interfaces()
102  for interface in interfaces:
103  _LOGGER.debug(
104  "Checking Motionblinds interface '%s' with host %s", interface, host
105  )
106  # initialize multicast listener
107  check_multicast = AsyncMotionMulticast(interface=interface)
108  try:
109  await check_multicast.Start_listen()
110  except socket.gaierror:
111  continue
112  except OSError:
113  continue
114 
115  # trigger test multicast
116  self._gateway_device_gateway_device = MotionGateway(
117  ip=host, key=key, multicast=check_multicast
118  )
119  result = await self._hass_hass.async_add_executor_job(self.check_interfacecheck_interface)
120 
121  # close multicast listener again
122  try:
123  check_multicast.Stop_listen()
124  except socket.gaierror:
125  continue
126 
127  if result:
128  # successfully received multicast
129  _LOGGER.debug(
130  "Success using Motionblinds interface '%s' with host %s",
131  interface,
132  host,
133  )
134  return interface
135 
136  _LOGGER.error(
137  (
138  "Could not find working interface for Motionblinds host %s, using"
139  " interface '%s'"
140  ),
141  host,
142  self._interface_interface,
143  )
144  return self._interface_interface
def __init__(self, hass, multicast=None, interface=None)
Definition: gateway.py:26