def data_handler(self, payload: Payload, delegation_event_whitelist=None):
        if delegation_event_whitelist is None:
            delegation_event_whitelist = []
        notify_all = payload.role == WILDCARD
        correct_payload = payload.role == ROLE
        is_request = payload.type in REQUEST_TYPES
        white_listed = payload.event in delegation_event_whitelist

        # 1. Determines if the payload is intended for the current unit
        if not correct_payload and is_request and not white_listed:

            # 2 If the current payload is NOT intended for the current unit
            #   it will be delegated, and hopefully send it to the appropriate
            #   unit.
            if IS_DELEGATOR and payload.role is not BLANK_FIELD:
                # 2.1 If delegation is enabled, it then gets the ip address of the intended
                #     unit and sends the payload, if the wildcard has been specified then all
                #     the units will be notified

                addresses = PiDiscovery.get_ip_addresses(payload.role)
                transactions = []
                res_payload = PayloadEventMessages.ADDRESS_NOT_FOUND.value
                for address in addresses:
                    client = LANClient(address, self.port, timeout=5, ignore_errors=True)
                    print("\t%s\n\t|\t\tRelaying -> %s:%s" % (print_payload(payload), address, self.port))
                    res_payload = client.send(payload)
                    transactions.append((res_payload.data, res_payload.event.name))

                if len(transactions) > 1:
                    payload.data = transactions
                    payload.type = PayloadType.RSP
                    return payload
                return res_payload

            else:
                # 2.2 If delegation is disabled, and the role can't be handled, then
                #     a error response will be sent telling the client 'Wrong Node'.
                if notify_all:
                    return self.process_payload(payload)
                return PayloadEventMessages.WRONG_NODE

        return self.process_payload(payload)
    def process_payload(self, payload: Payload):
        res_payload = payload
        is_resp = payload.type not in REQUEST_TYPES
        is_soft = payload.event in SOFTWARE_TYPES
        is_hard = payload.event in HARDWARE_TYPES
        is_sys = payload.event in SYSTEM_TYPES

        print(
            "[i] Processing %s %s (%s)"
            % (
                "Hardware" if is_hard else ("Software" if is_soft else ("System" if is_sys else "Unknown")),
                "Response" if is_resp else "Request",
                print_payload(payload),
            )
        )

        # --------------------SYSTEM HANDLING--------------------
        if is_sys:
            if is_resp:
                # Response handling
                # TODO: Handle response
                pass

            else:
                # Request handling
                # Handles Probe Request
                if payload.event is PayloadEvent.S_PROBE:
                    res_payload.data = {"name": NAME, "role": ROLE, "isDelegator": IS_DELEGATOR}
                    res_payload.type = PayloadType.RSP
                # TODO: Handle requests

                # ------------------HARDWARE/SOFTWARE HANDLING------------------------
        if is_hard or is_soft:
            domain = EventDomain.SOFT if is_soft else (EventDomain.GPIO if is_hard else None)
            print("\t%s Instruction <%s --> %s>" % (domain.value, payload.data, payload.event))
            return self.handler.instruction(self, payload.data, payload.event, domain, payload)
        return res_payload
 def received(self, req_payload: Payload, res_payload: Payload):
     print("\n\t| REQ:%s\n\t| RSP:%s\n" % (print_payload(req_payload),
                                           print_payload(res_payload)))
     pass