Exemple #1
0
    def _handle_client_sync(self, req: Request):
        """
        Handles a client update request from any foreign source

        :param req: Request containing the client update request
        :return: None
        """
        try:
            self._validator.validate(req.get_payload(), "api_client_sync_request")
        except ValidationError as err:
            self._respond_with_error(req,
                                     "ValidationError",
                                     f"Request validation error at '{ApiURIs.sync_client.uri}': '{err.message}'")
            return

        client_id = req.get_sender()

        self._logger.info(f"Syncing client {client_id}")

        decoder = ApiDecoder()

        new_client = decoder.decode_client(req.get_payload()["client"], req.get_sender())

        gadget_data = req.get_payload()["gadgets"]

        for gadget in gadget_data:
            self._update_gadget(client_id, gadget)

        self._delegate.handle_client_sync(new_client)
Exemple #2
0
    def _handle_heartbeat(self, req: Request):
        try:
            self._validator.validate(req.get_payload(), "bridge_heartbeat_request")
        except ValidationError:
            self._respond_with_error(req, "ValidationError", f"Request validation error at '{ApiURIs.heartbeat.uri}'")
            return

        rt_id = req.get_payload()["runtime_id"]
        self._delegate.handle_heartbeat(req.get_sender(), rt_id)
Exemple #3
0
    def _handle_update_gadget(self, req: Request):
        """
        Handles a characteristic update request, for a gadget, from any foreign source

        :param req: Request containing the gadget update request
        :return: None
        """
        try:
            self._validator.validate(req.get_payload(), "api_gadget_update_request")
        except ValidationError:
            self._respond_with_error(req, "ValidationError",
                                     f"Request validation error at '{ApiURIs.update_gadget.uri}'")
            return

        try:
            gadget_update_info = ApiDecoder().decode_gadget_update(req.get_payload())
        except GadgetDecodeError:
            self._respond_with_error(req,
                                     "GadgetDecodeError",
                                     f"Gadget update decode error at '{ApiURIs.sync_client.uri}'")
            return

        client_id = req.get_sender()

        gadget_info = [x for x in self._delegate.get_gadget_info() if x.get_name() == req.get_payload()["id"]]
        if not gadget_info:
            self._respond_with_error(req, "GagdetDoesNeeExist", "Sadly, no gadget with the given id exists")
            return

        gadget = gadget_info[0]

        updated_characteristics = [x.id for x in gadget_update_info.characteristics]
        buf_characteristics = [x for x in gadget.get_characteristics() if x.get_type() in updated_characteristics]

        for c in buf_characteristics:
            value = [x.step_value for x in gadget_update_info.characteristics if x.id == c.get_type()][0]
            c.set_step_value(value)

        out_gadget = AnyGadget(gadget_update_info.id,
                               req.get_sender(),
                               buf_characteristics)

        self._logger.info(f"Updating {len(buf_characteristics)} gadget characteristics from '{client_id}'")
        self._delegate.handle_gadget_update(out_gadget)
Exemple #4
0
 def mock_response_function(req: Request, payload: dict, path: str):
     if path is None:
         buf_path = req.get_path()
     else:
         buf_path = path
     out_req = Request(path=buf_path,
                       session_id=req.get_session_id(),
                       sender=req.get_receiver(),
                       receiver=req.get_sender(),
                       payload=payload)
     self._last_response = out_req
Exemple #5
0
    def _respond_to(self,
                    req: Request,
                    payload: dict,
                    path: Optional[str] = None):
        if path:
            out_path = path
        else:
            out_path = req.get_path()

        receiver = req.get_sender()

        out_req = Request(out_path, req.get_session_id(), self._host_name,
                          receiver, payload)

        self._send(out_req)
Exemple #6
0
        def respond(req: Request, payload: dict, path: Optional[str]):
            if req.get_session_id() != self._request.get_session_id():
                raise IllegalResponseException(
                    f"Session IDs {req.get_session_id()} and "
                    f"{self._request.get_session_id()} are not matching")
            if path is not None:
                res_path = path
            else:
                res_path = req.get_path()

            self._response = Request(path=res_path,
                                     session_id=req.get_session_id(),
                                     sender=self._request.get_receiver(),
                                     receiver=req.get_sender(),
                                     payload=payload)
    def wait_for_responses(self,
                           out_req: Request,
                           timeout: int = 5,
                           max_resp_count: Optional[int] = 1) -> list[Request]:
        if not self._keep_queue:
            self._request_queue = Queue()
        else:
            self._keep_queue = False

        responses: list[Request] = []
        timeout_time = datetime.now() + timedelta(seconds=timeout)

        while timeout and datetime.now() < timeout_time:
            if max_resp_count and len(
                    responses
            ) >= max_resp_count:  # return responses if enough are collected
                return responses
            if not self._request_queue.empty():
                res: Request = self._request_queue.get()
                if res.get_session_id() == out_req.get_session_id(
                ) and out_req.get_sender() != res.get_sender():
                    responses.append(res)

        return responses
Exemple #8
0
    def send_request_split(self,
                           path: str,
                           receiver: str,
                           payload: dict,
                           part_max_size: int = 30,
                           timeout: Optional[int] = None) -> Optional[Request]:
        """
        Sends a request to all attached networks.
        The request will be split into individual parts with a maximum length.

        :param path: Path to send the request on
        :param receiver: Receiver for the Request
        :param payload: Payload to be send
        :param part_max_size: Maximum size in bytes for each individual payload chunk
        :param timeout: Maximum timeout to wait for an answer
        :return: The response if there is any
        """
        if timeout is None:
            timeout = self._default_timeout
        req = Request(path, None, self._hostname, receiver, payload)
        session_id = req.get_session_id()
        path = req.get_path()
        sender = req.get_sender()
        receiver = req.get_receiver()

        payload_str = json.dumps(req.get_payload())

        # Make string ready to be contained in json itself
        payload_str = payload_str.replace('"', "$*$")

        payload_len = len(payload_str)
        parts = []
        start = 0
        package_index = 0

        while start < payload_len:
            end = start + part_max_size
            payload_part = payload_str[start:(
                end if end < payload_len else payload_len)]
            parts.append(payload_part)
            start = end

        last_index = len(parts)

        for payload_part in parts:

            out_dict = {
                "package_index": package_index,
                "split_payload": payload_part
            }
            if package_index == 0:
                out_dict["last_index"] = last_index

            out_req = Request(path, session_id, sender, receiver, out_dict)
            if package_index == last_index - 1:
                responses = self._send_request_obj(out_req, timeout, 1)
                if not responses:
                    return None
                return responses[0]
            else:
                self._send_request_obj(out_req, 0, 0)
            package_index += 1
            sleep(0.1)
        return None
 def receive(self, req: Request):
     if req.get_sender() not in self._clients:
         self._clients.append(req.get_sender())