Join the local audience
        (a config message should be received on success)
        Validates that there are people to join and that each of them
        has a valid unique id

        :param people: Which people does this sensor have
        :type people: list[paps.person.Person]
        :rtype: None
        :raises SensorJoinException: Failed to join

def join(self, people):
        """
        Join the local audience
        (a config message should be received on success)
        Validates that there are people to join and that each of them
        has a valid unique id

        :param people: Which people does this sensor have
        :type people: list[paps.person.Person]
        :rtype: None
        :raises SensorJoinException: Failed to join
        """
        tries = 0
        if not people:
            raise SensorJoinException("No people given")
        ids = set()
        for person in people:
            if not person.id and person.id != 0:
                raise SensorJoinException("Invalid id for one or more people")
            if person.id in ids:
                raise SensorJoinException(
                    u"Id {} not unique".format(person.id)
                )
            ids.add(person.id)

        while self._is_running and tries < self._join_retry_count:
            packet = APPJoinMessage(
                payload={'people': [person.to_dict() for person in people]}
            )
            self._send_packet(self._multicast_group, self._multicast_port,
                              packet)
            if self._joined.wait(self._join_retry_timeout):
                break
            with self._seq_ack_lock:
                # Got ack for packet?
                packet_ackd = packet.header.sequence_number \
                    not in self._seq_ack
            if packet_ackd and self._joined.wait(1.0):
                # Packet already got acked
                # -> wait another second for ._joined to clear
                break
            tries += 1
            self.warning(
                u"Unsuccessful attempt joining audience # {}".format(tries)
            )

        if not self._joined.is_set() or tries >= self._join_retry_count:
            # Failed to join (no config packet received)
            raise SensorJoinException("No config packet received")
        self.info("Joined the audience")