docs: def async_login(self):
         """Login to Alarm.com."""
         _LOGGER.debug('Attempting to log into Alarm.com...')
  
         # Get the session key for future logins.
         response = None
         try:
             with async_timeout.timeout(10, loop=self._loop):
                 response = yield from self._websession.get(
                     self.ALARMDOTCOM_URL + '/default.aspx',
                 headers={'User-Agent': 'Mozilla/5.0 '
                                        '(Windows NT 6.1;'
                                        ' WOW64; rv:40.0) '
                                        'Gecko/20100101 '
                                        'Firefox/40.1'})
  
             _LOGGER.debug(
                 'Response status from Alarm.com: %s',
                 response.status)
             text = yield from response.text()
             _LOGGER.debug(text)
             tree = BeautifulSoup(text, 'html.parser')
             self._login_info = {
                 'sessionkey': self.SESSION_KEY_RE.match(
                     str(response.url)).groupdict()['sessionKey'],
                 self.VIEWSTATE: tree.select(
                     '#{}'.format(self.VIEWSTATE))[0].attrs.get('value'),
                 self.VIEWSTATEGENERATOR: tree.select(
                     '#{}'.format(self.VIEWSTATEGENERATOR))[0].attrs.get('value'),
                 self.EVENTVALIDATION: tree.select(
                     '#{}'.format(self.EVENTVALIDATION))[0].attrs.get('value')
             }
  
             _LOGGER.debug(self._login_info)
             _LOGGER.info('Attempting login to Alarm.com')
  
         except (asyncio.TimeoutError, aiohttp.ClientError):
             _LOGGER.error('Can not get login page from Alarm.com')
             return False
         except AttributeError:
             _LOGGER.error('Unable to get sessionKey from Alarm.com')
             raise
  
          # Login params to pass during the post
         params = {
             self.USERNAME: self._username,
             self.PASSWORD: self._password,
             self.VIEWSTATE: self._login_info[self.VIEWSTATE],
             self.VIEWSTATEGENERATOR: self._login_info[self.VIEWSTATEGENERATOR],
             self.EVENTVALIDATION: self._login_info[self.EVENTVALIDATION]
         }
  
         try:
             # Make an attempt to log in.
             with async_timeout.timeout(10, loop=self._loop):
                 response = yield from self._websession.post(
                     self.ALARMDOTCOM_URL + '{}/default.aspx'.format(
                         self._login_info['sessionkey']),
                     data=params,
                     headers={'User-Agent': 'Mozilla/5.0 '
                                            '(Windows NT 6.1; '
                                            'WOW64; rv:40.0) '
                                            'Gecko/20100101 '
                                            'Firefox/40.1'}
                 )
             _LOGGER.debug(
                 'Status from Alarm.com login %s', response.status)
  
             # Alarm.com changed their redirect so hit this page directly to get the status of login.
             with async_timeout.timeout(10, loop=self._loop):
                 response = yield from self._websession.get(
                     self.ALARMDOTCOM_URL + '{}/main.aspx'.format(
                         self._login_info['sessionkey']),
                     headers={'User-Agent': 'Mozilla/5.0 '
                                            '(Windows NT 6.1; '
                                            'WOW64; rv:40.0) '
                                            'Gecko/20100101 '
                                            'Firefox/40.1'}
                 )
  
             # Get the text from the login to ensure that we are logged in.
             text = yield from response.text()
             _LOGGER.debug(text)
             tree = BeautifulSoup(text, 'html.parser')
             try:
                 self.state = tree.select(self.ALARM_STATE)[0].get_text()
                 _LOGGER.debug(
                     'Current alarm state: %s', self.state)
                 self.sensor_status = tree.select(self.SENSOR_STATUS)[0].get_text()
                 _LOGGER.debug(
                     'Current sensor status: %s', self.sensor_status)
             except IndexError:
                 try:
                     error_control = tree.select(
                         '#{}'.format(self.ERROR_CONTROL))[0].attrs.get('value')
                     if 'Login failure: Bad Credentials' in error_control:
                         _LOGGER.error(error_control)
                         return False
                 except AttributeError:
                     _LOGGER.error('Error while trying to log into Alarm.com')
                     return False
         except (asyncio.TimeoutError, aiohttp.ClientError):
             _LOGGER.error("Can not load login page from Alarm.com")
             return False