docs: def auth(self):
          """Authenticate using the SOAP interface.
  
          Authentication is a two-step process. First a initial payload
          is sent to the device requesting additional login information in the form
          of a publickey, a challenge string and a cookie.
          These values are then hashed by a MD5 algorithm producing a privatekey
          used for the header and a hashed password for the XML payload.
  
          If everything is accepted the XML returned will contain a LoginResult tag with the
          string 'success'.
  
          See https://github.com/bikerp/dsp-w215-hnap/wiki/Authentication-process for more information.
          """
  
          payload = self.initial_auth_payload()
  
          # Build initial header
          headers = {'Content-Type' : '"text/xml; charset=utf-8"',
             'SOAPAction': '"http://purenetworks.com/HNAP1/Login"'}
  
          # Request privatekey, cookie and challenge
          try:
              response = urlopen(Request(self.url, payload, headers))
          except URLError:
              if self._error_report is False:
                  _LOGGER.warning('Unable to open a connection to dlink switch {}'.format(self.ip))
                  self._error_report = True
              return None
          xmlData = response.read().decode()
          root = ET.fromstring(xmlData)
  
          # Find responses
          ChallengeResponse = root.find('.//{http://purenetworks.com/HNAP1/}Challenge')
          CookieResponse = root.find('.//{http://purenetworks.com/HNAP1/}Cookie')
          PublickeyResponse = root.find('.//{http://purenetworks.com/HNAP1/}PublicKey')
  
          if (ChallengeResponse == None or CookieResponse == None or PublickeyResponse == None) and self._error_report is False:
              _LOGGER.warning("Failed to receive initial authentication from smartplug.")
              self._error_report = True
              return None
  
          if self._error_report is True:
              return None
  
          Challenge = ChallengeResponse.text
          Cookie = CookieResponse.text
          Publickey = PublickeyResponse.text
  
          # Generate hash responses
          PrivateKey = hmac.new((Publickey+self.password).encode(), (Challenge).encode()).hexdigest().upper()
          login_pwd = hmac.new(PrivateKey.encode(), Challenge.encode()).hexdigest().upper()
  
          response_payload = self.auth_payload(login_pwd)
          # Build response to initial request
          headers = {'Content-Type' : '"text/xml; charset=utf-8"',
             'SOAPAction': '"http://purenetworks.com/HNAP1/Login"',
             'HNAP_AUTH' : '"{}"'.format(PrivateKey),
             'Cookie' : 'uid={}'.format(Cookie)}
          response = urlopen(Request(self.url, response_payload, headers))
          xmlData = response.read().decode()
          root = ET.fromstring(xmlData)
  
          # Find responses
          login_status = root.find('.//{http://purenetworks.com/HNAP1/}LoginResult').text.lower()
  
          if login_status != "success" and self._error_report is False:
              _LOGGER.error("Failed to authenticate with SmartPlug {}".format(self.ip))
              self._error_report = True
              return None
  
          self._error_report = False # Reset error logging
          return (PrivateKey, Cookie)