docs: def discover(service="ssdp:all", timeout=1, retries=2, ipAddress="239.255.255.250", port=1900):
          """Discovers UPnP devices in the local network.
  
          Try to discover all devices in the local network which do support UPnP. The discovery process can fail
          for various reasons and it is recommended to do at least two discoveries, which you can specify with the
          ``retries`` parameter.
  
          The default ``service`` parameter tries to address all devices also if you know which kind of service type
          you are looking for you should set it as some devices do not respond or respond differently otherwise.
  
          :param service: the service type or list of service types of devices you look for
          :type service: str or list[str]
          :param float timeout: the socket timeout for each try
          :param int retries: how often should be a discovery request send
          :param str ipAddress: the multicast ip address to use
          :param int port: the port to use
          :return: a list of DiscoveryResponse objects or empty if no device was found
          :rtype: list[DiscoveryResponse]
  
          Example:
            ::
  
              results = discover()
              for result in results:
                  print("Host: " + result.locationHost + " Port: " + result.locationPort + " Device definitions: " + \\
                      result.location)
  
          .. seealso::
  
              :class:`~simpletr64.DiscoveryResponse`, :meth:`~simpletr64.Discover.discoverParticularHost`
          """
  
          socket.setdefaulttimeout(timeout)
  
          messages = []
  
          if isinstance(service, str):
              services = [service]
          elif isinstance(service, list):
              services = service
  
          for service in services:
              message = 'M-SEARCH * HTTP/1.1\r\nMX: 5\r\nMAN: "ssdp:discover"\r\nHOST: ' + \
                        ipAddress + ':' + str(port) + '\r\n'
              message += "ST: " + service + "\r\n\r\n"
              messages.append(message)
  
          responses = {}
  
          for _ in range(retries):
  
              # setup the socket
              sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
              sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
              sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
  
              # noinspection PyAssignmentToLoopOrWithParameter
              for _ in range(2):
  
                  # send the messages with different service types
                  for message in messages:
                      # send message more often to make sure all devices will get it
                      sock.sendto(message.encode('utf-8'), (ipAddress, port))
  
              while True:
                  try:
                      # read the message until timeout
                      data = sock.recv(1024)
                  except socket.timeout:
                      break
                  else:
                      # no time out, read the response data and create response object
                      response = DiscoveryResponse(data)
                      # filter duplicated responses
                      responses[response.location] = response
  
          # return a list of all responses
          return list(responses.values())