docs: async def start(self):
          """Connect to device and listen to incoming messages."""
          if self.connection.connected:
              return
  
          await self.connection.connect()
  
          # In case credentials have been given externally (i.e. not by pairing
          # with a device), then use that client id
          if self.service.device_credentials:
              self.srp.pairing_id = Credentials.parse(
                  self.service.device_credentials).client_id
  
          # The first message must always be DEVICE_INFORMATION, otherwise the
          # device will not respond with anything
          msg = messages.device_information(
              'pyatv', self.srp.pairing_id.decode())
          await self.send_and_receive(msg)
          self._initial_message_sent = True
  
          # This should be the first message sent after encryption has
          # been enabled
          await self.send(messages.set_ready_state())
  
          async def _wait_for_updates(_, semaphore):
              # Use a counter here whenever more than one message is expected
              semaphore.release()
  
          # Wait for some stuff to arrive before returning
          semaphore = asyncio.Semaphore(value=0, loop=self.loop)
          self.add_listener(_wait_for_updates,
                            protobuf.SET_STATE_MESSAGE,
                            data=semaphore,
                            one_shot=True)
  
          # Subscribe to updates at this stage
          await self.send(messages.client_updates_config())
          await self.send(messages.wake_device())
  
          try:
              await asyncio.wait_for(
                  semaphore.acquire(), 1, loop=self.loop)
          except asyncio.TimeoutError:
              # This is not an issue itself, but I should do something better.
              # Basically this gives the device about one second to respond with
              # some metadata before continuing.
              pass