async def scan(self, scanning_radius_km: int, minimal_radius_m: int,
                   result_cb: Callable[[ObjectsList, Error],
                                       None], timeout: float) -> Optional[str]:
        """Scanning all bodies within a 'scanning_radius_km' radius.

        Bodies with radius less then the specified 'minimal_radius_m' will be
        ignored. The 'result_cb' callback will be called when another portion
        of data received from the server. After all data received callback
        will be called for the last time with (None, None) argument.
        Return None on success otherwise return error string
        """
        request = api.Message()
        scan_req = request.celestial_scanner.scan
        scan_req.scanning_radius_km = scanning_radius_km
        scan_req.minimal_radius_m = minimal_radius_m
        if not self.send(message=request):
            error = "Failed to send request"
            result_cb(None, error)
            return error

        continue_scanning = True
        while continue_scanning:
            response, _ = await self.wait_message(timeout=timeout)
            body = api.get_message_field(response, ["celestial_scanner"])
            if not body:
                error = "No response"
                result_cb(None, error)
                return error

            report = api.get_message_field(body, ["scanning_report"])
            if not report:
                fail = api.get_message_field(body, ["scanning_failed"])
                if fail:
                    error = CelestialScannerI.Status.convert(fail).value
                else:
                    error = self.__unexpected_msg_str(fail)
                result_cb(None, error)
                return error

            timestamp: Optional[int] = response.timestamp or None
            result_cb([
                self.__build_object(body, timestamp)
                for body in report.asteroids
            ], None)
            continue_scanning = report.left > 0

        result_cb(None, None)  # Scanning is finished
        return None
Example #2
0
 async def wait_state(self, timeout: float = 0.5) -> Optional[State]:
     """Await a State message with actual ship's state"""
     message, timestamp = await self.wait_message(timeout)
     if not message:
         return None
     state = api.get_message_field(message, ["ship", "state"])
     return State.build(state, timestamp) if state else None
Example #3
0
 async def wait_timestamp(self, timeout: float = 0.5) -> Optional[int]:
     """Wait for a 'time' message, that carries current system clock's time"""
     response, _ = await self.wait_message(timeout=timeout)
     if not response:
         self.logger.warning("Timeout while waiting timestamp")
         return None
     return api.get_message_field(response, ["system_clock", "time"])
 async def _wait_start_mining_status(self, timeout: float = 1) -> Status:
     response, _ = await self.wait_message(timeout=timeout)
     if not response:
         return AsteroidMinerI.Status.RESPONSE_TIMEOUT
     mining_status = api.get_message_field(
         response, ["asteroid_miner", "start_mining_status"])
     if mining_status is None:
         return AsteroidMinerI.Status.UNEXPECTED_RESPONSE
     return AsteroidMinerI.Status.from_protobuf(mining_status)
Example #5
0
 async def wait_building_report(self, timeout: float = 1.0) -> \
         (Status, Optional[float]):
     response, _ = await self.wait_message(timeout=timeout)
     if not response:
         return ShipyardI.Status.RESPONSE_TIMEOUT, None
     report = api.get_message_field(response,
                                    ["shipyard", "building_report"])
     if not report:
         return ShipyardI.Status.UNEXPECTED_RESPONSE, None
     return ShipyardI.Status.from_protobuf(report.status), report.progress
    async def transfer(self,
                       port: int,
                       access_key: int,
                       resource: ResourceItem,
                       progress_cb: Optional[Callable[[ResourceItem],
                                                      None]] = None,
                       timeout: int = 0.5) -> Status:
        """Transfer the specified 'resource' to the specified 'port' with the
        specified 'access_key'. The optionally specified 'progress_cb' will be
        called to report transferring status (a total amount of transferred
        resources)."""
        request = api.Message()
        req_body = request.resource_container.transfer
        req_body.port_id = port
        req_body.access_key = access_key
        resource_item = req_body.resource
        resource.to_protobuf(resource_item)

        if not self.send(message=request):
            return ResourceContainerI.Status.FAILED_TO_SEND_REQUEST
        response, _ = await self.wait_message(timeout=timeout)
        if not response:
            return ResourceContainerI.Status.RESPONSE_TIMEOUT
        status = api.get_message_field(
            response, ["resource_container", "transfer_status"])
        if status is None:
            return ResourceContainerI.Status.UNEXPECTED_RESPONSE
        if status != api.IResourceContainer.Status.SUCCESS:
            return ResourceContainerI.Status.convert(status)
        # Status is success. Waiting for reports
        while True:
            response, _ = await self.wait_message(timeout=2)
            report = api.get_message_field(
                response, ["resource_container", "transfer_report"])
            if not report:
                # May be complete status is received:
                status = api.get_message_field(
                    response, ["resource_container", "transfer_finished"])
                return ResourceContainerI.Status.convert(status) \
                    if status is not None else ResourceContainerI.Status.UNEXPECTED_RESPONSE
            # Got transfer report:
            if progress_cb is not None:
                progress_cb(ResourceItem.from_protobuf(report))
Example #7
0
    async def wait_until(self, time: int, timeout: float) -> Optional[int]:
        """Wait until server time reaches the specified 'time'

        Return actual server's time"""
        request = api.Message()
        request.system_clock.wait_until = time
        if not self.send(message=request):
            return None
        response, _ = await self.wait_message(timeout=timeout)
        if not response:
            return None
        return api.get_message_field(response, ["system_clock", "ring"])
Example #8
0
    async def get_blueprint(self,
                            blueprint_name: str,
                            timeout: float = 0.5) \
            -> (Status, Optional[Blueprint]):
        request = api.Message()
        request.blueprints_library.blueprint_req = blueprint_name
        if not self.send(request):
            return Status.FAILED_TO_SEND_REQUEST, None
        response, _ = await self.wait_message(timeout=timeout)
        if not response:
            return Status.RESPONSE_TIMEOUT, None

        blueprint = api.get_message_field(response,
                                          ["blueprints_library", "blueprint"])
        if blueprint:
            return Status.SUCCESS, Blueprint.from_protobuf(blueprint)

        fail = api.get_message_field(response,
                                     ["blueprints_library", "blueprint_fail"])
        if fail:
            return Status.from_protobuf(fail), None
    async def _wait_mining_report(self, timeout: float) \
            -> (Status, Optional[ResourcesDict]):
        response, _ = await self.wait_message(timeout=timeout)
        if not response:
            return AsteroidMinerI.Status.RESPONSE_TIMEOUT, None
        report = api.get_message_field(response,
                                       ["asteroid_miner", "mining_report"])
        if report is not None:
            resources = {
                ResourceType.from_protobuf(item.type): item.amount
                for item in report.items
            }
            return AsteroidMinerI.Status.SUCCESS, resources

        # May be mining was interrupted, that is why we haven't received the report?
        stop_ind = api.get_message_field(
            response, ["asteroid_miner", "mining_is_stopped"])
        if stop_ind is not None:
            return AsteroidMinerI.Status.from_protobuf(stop_ind), None

        return AsteroidMinerI.Status.UNEXPECTED_RESPONSE, None
Example #10
0
    async def wait_for(self, period_us: int, timeout: float) -> Optional[int]:
        """Wait for the specified 'period' microseconds

        Return actual server's time"""
        request = api.Message()
        request.system_clock.wait_for = period_us
        if not self.send(message=request):
            return None
        response, _ = await self.wait_message(timeout=timeout)
        if not response:
            return None
        return api.get_message_field(response, ["system_clock", "ring"])
Example #11
0
 async def wait_building_complete(self, timeout: float = 1.0) -> \
         (Status, Optional[str], Optional[int]):
     response, _ = await self.wait_message(timeout=timeout)
     if not response:
         return ShipyardI.Status.RESPONSE_TIMEOUT, None, None
     report = api.get_message_field(response,
                                    ["shipyard", "building_complete"])
     if not report:
         return ShipyardI.Status.UNEXPECTED_RESPONSE, None, None
     return ShipyardI.Status.SUCCESS, \
            report.ship_name, \
            report.slot_id
 async def start_monitoring(self, timeout: float = 0.5) -> Status:
     request = api.Message()
     request.passive_scanner.monitor = True
     if not self.send(message=request):
         return PassiveScannerI.Status.FAILED_TO_SEND_REQUEST
     response, _ = await self.wait_message(timeout=timeout)
     if not response:
         return PassiveScannerI.Status.RESPONSE_TIMEOUT
     ack = api.get_message_field(response,
                                 ["passive_scanner", "monitor_ack"])
     return PassiveScannerI.Status.SUCCESS \
         if ack else PassiveScannerI.Status.MONITORING_FAILED
Example #13
0
 async def get_thrust(self, timeout: float = 0.5) -> Optional[Vector]:
     """Return current engine thrust"""
     request = api.Message()
     request.engine.thrust_req = True
     if not self.send(message=request):
         return None
     response, _ = await self.wait_message(timeout=timeout)
     if not response:
         return None
     thrust = api.get_message_field(response, ["engine", "thrust"])
     if not thrust:
         return None
     return Vector(x=thrust.x, y=thrust.y).set_length(thrust.thrust)
Example #14
0
 async def wait_message(self, timeout: float = 1.0) -> \
         Tuple[Optional[Any], Optional[int]]:
     """Await for a message on the internal queue for not more than the
     specified 'timeout' seconds. Return a message and an optional timestamp,
     when the message was sent."""
     try:
         message, timestamp = \
             await asyncio.wait_for(self.queue.get(), timeout=timeout)
         if get_message_field(message, ["session", "closed_ind"]):
             raise ChannelClosed()
         return message, timestamp
     except asyncio.TimeoutError:
         return None, None
 async def get_specification(self, timeout: float = 0.5)\
         -> Optional[Specification]:
     request = api.Message()
     request.passive_scanner.specification_req = True
     if not self.send(message=request):
         return None
     response, _ = await self.wait_message(timeout=timeout)
     if not response:
         return None
     spec = api.get_message_field(response, ["passive_scanner", "specification"])
     if not spec:
         return None
     return Specification(scanning_radius_km=spec.scanning_radius_km,
                          max_update_time_ms=spec.max_update_time_ms)
Example #16
0
 async def wait_exact(self, message: List[str], timeout: float = 1.0) \
         -> Tuple[Optional[Any], Optional[int]]:
     """Await for the specified 'message' but not more than 'timeout' seconds.
     Ignore all other received messages. Return expected message and timestamp or
     None"""
     while timeout > 0:
         start_at = time.monotonic()
         received_msg, timestemp = await self.wait_message(timeout)
         expected_msg = get_message_field(received_msg, message)
         if expected_msg is not None:
             return expected_msg, timestemp
         # Got unexpected message. Just ignoring it
         timeout -= time.monotonic() - start_at
     return None, None
 async def close_port(self, timeout: int = 0.5) -> Status:
     """Close an existing opened port"""
     request = api.Message()
     request.resource_container.close_port = True
     if not self.send(message=request):
         return ResourceContainerI.Status.FAILED_TO_SEND_REQUEST
     response, _ = await self.wait_message(timeout=timeout)
     if not response:
         return ResourceContainerI.Status.RESPONSE_TIMEOUT
     status = api.get_message_field(
         response, ["resource_container", "close_port_status"])
     if status is not None:
         # Success case
         return ResourceContainerI.Status.convert(status)
    async def open_port(self,
                        access_key: int,
                        timeout: int = 0.5) -> (Status, int):
        """Open a new port with the specified 'access_key'. Return operation status
        and port number"""
        request = api.Message()
        request.resource_container.open_port = access_key
        if not self.send(message=request):
            return ResourceContainerI.Status.FAILED_TO_SEND_REQUEST, 0
        response, _ = await self.wait_message(timeout=timeout)
        if not response:
            return ResourceContainerI.Status.RESPONSE_TIMEOUT, 0
        port_id = api.get_message_field(response,
                                        ["resource_container", "port_opened"])
        if port_id is not None:
            # Success case
            return ResourceContainerI.Status.SUCCESS, port_id

        error_status = api.get_message_field(
            response, ["resource_container", "open_port_failed"])
        if error_status is not None:
            return ResourceContainerI.Status.convert(error_status), 0
        return ResourceContainerI.Status.UNEXPECTED_RESPONSE, 0
Example #19
0
 async def get_specification(self, timeout: float = 0.5) \
         -> (Status, Optional[Specification]):
     request = api.Message()
     request.shipyard.specification_req = True
     if not self.send(message=request):
         return ShipyardI.Status.FAILED_TO_SEND_REQUEST, None
     response, _ = await self.wait_message(timeout=timeout)
     if not response:
         return ShipyardI.Status.RESPONSE_TIMEOUT, None
     spec = api.get_message_field(response, ["shipyard", "specification"])
     if not spec:
         return ShipyardI.Status.UNEXPECTED_RESPONSE, None
     spec = Specification(labor_per_sec=spec.labor_per_sec)
     return ShipyardI.Status.SUCCESS, spec
Example #20
0
 async def bind_to_cargo(self,
                         cargo_name: str,
                         timeout: float = 0.5) -> Status:
     request = api.Message()
     request.shipyard.bind_to_cargo = cargo_name
     if not self.send(message=request):
         return ShipyardI.Status.FAILED_TO_SEND_REQUEST
     response, _ = await self.wait_message(timeout=timeout)
     if not response:
         return ShipyardI.Status.RESPONSE_TIMEOUT
     status = api.get_message_field(response,
                                    ["shipyard", "bind_to_cargo_status"])
     if status is None:
         return ShipyardI.Status.UNEXPECTED_RESPONSE
     return ShipyardI.Status.from_protobuf(status)
 async def get_specification(self, timeout: float = 0.5)\
         -> Optional[Specification]:
     request = api.Message()
     request.celestial_scanner.specification_req = True
     if not self.send(message=request):
         return None
     response, _ = await self.wait_message(timeout=timeout)
     if not response:
         return None
     spec = api.get_message_field(response,
                                  ["celestial_scanner", "specification"])
     if not spec:
         return None
     return Specification(max_radius_km=spec.max_radius_km,
                          processing_time_us=spec.processing_time_us)
Example #22
0
    async def set_position(self, center_x: float, center_y: float,
                           width: float, height: float):
        """Move screen with the specified 'width' and 'height' to
        the specified 'x' and 'y' position"""
        message = api.admin.Message()
        position = message.screen.move
        position.x = center_x
        position.y = center_y
        position.width = width
        position.height = height
        self.send(message)

        response = await self.wait_message()
        status = api.get_message_field(response, ["screen", "status"])
        return status is not None and status == api.admin.Screen.Status.SUCCESS
    async def stop_mining(self, timeout: float = 0.5) -> Status:
        """Stop the mining process"""
        request = api.Message()
        request.asteroid_miner.stop_mining = True
        if not self.send(message=request):
            return AsteroidMinerI.Status.FAILED_TO_SEND_REQUEST

        response, _ = await self.wait_message(timeout=timeout)
        if not response:
            return AsteroidMinerI.Status.RESPONSE_TIMEOUT
        status = api.get_message_field(
            response, ["asteroid_miner", "stop_mining_status"])
        if status is None:
            return AsteroidMinerI.Status.UNEXPECTED_RESPONSE
        return AsteroidMinerI.Status.from_protobuf(status)
Example #24
0
 async def get_position(self, timeout: float = 0.5) -> Optional[Position]:
     """Request current ship's position. Will block until the response
     is received or the specified 'timeout' occurs."""
     request = api.Message()
     request.navigation.position_req = True
     if not self.send(message=request):
         return None
     response, _ = await self.wait_message(timeout=timeout)
     if not response:
         return None
     position = api.get_message_field(response, ["navigation", "position"])
     if not position:
         return None
     assert response.timestamp is not None
     return Position.from_protobuf(position, timestamp=response.timestamp)
 async def bind_to_cargo(self,
                         cargo_name: str,
                         timeout: float = 0.5) -> Status:
     """Bind miner to the container with the specified 'cargo_name'"""
     request = api.Message()
     request.asteroid_miner.bind_to_cargo = cargo_name
     if not self.send(message=request):
         return AsteroidMinerI.Status.FAILED_TO_SEND_REQUEST
     response, _ = await self.wait_message(timeout=timeout)
     if not response:
         return AsteroidMinerI.Status.RESPONSE_TIMEOUT
     protobuf_status = api.get_message_field(
         response, ["asteroid_miner", "bind_to_cargo_status"])
     if protobuf_status is None:
         return AsteroidMinerI.Status.UNEXPECTED_RESPONSE
     return AsteroidMinerI.Status.from_protobuf(protobuf_status)
Example #26
0
    async def show(self, object_type: ObjectType) -> List[PhysicalObject]:
        message = api.admin.Message()
        message.screen.show = object_type.to_protobuf_type()
        self.send(message)

        shown_objects: List[PhysicalObject] = []

        while True:
            response = await self.wait_message()
            items = api.get_message_field(response, ["screen", "objects"])
            if not items:
                break
            for item in items.object:
                shown_objects.append(PhysicalObject().from_protobuf(item))
            if items.left == 0:
                break
        return shown_objects
 async def wait_content(self, timeout: float = 0.5) -> \
         Tuple[Status, Optional[Content]]:
     response, timestamp = await self.wait_message(timeout=timeout)
     if not response:
         return ResourceContainerI.Status.FAILED_TO_SEND_REQUEST, None
     content = api.get_message_field(response,
                                     ["resource_container", "content"])
     if not content:
         return ResourceContainerI.Status.RESPONSE_TIMEOUT, None
     content = ResourceContainerI.Content(timestamp=timestamp,
                                          volume=content.volume,
                                          used=content.used,
                                          resources={
                                              ResourceType.from_protobuf(
                                                  item.type): item.amount
                                              for item in content.resources
                                          })
     return ResourceContainerI.Status.SUCCESS, content
 async def get_specification(self, timeout: float = 0.5)\
         -> (Status, Optional[Specification]):
     status = AsteroidMinerI.Status
     request = api.Message()
     request.asteroid_miner.specification_req = True
     if not self.send(message=request):
         return status.FAILED_TO_SEND_REQUEST, None
     response, _ = await self.wait_message(timeout=timeout)
     if not response:
         return status.RESPONSE_TIMEOUT, None
     spec = api.get_message_field(response,
                                  ["asteroid_miner", "specification"])
     if not spec:
         return status.UNEXPECTED_RESPONSE, None
     spec = Specification(max_distance=spec.max_distance,
                          cycle_time_ms=spec.cycle_time_ms,
                          yield_per_cycle=spec.yield_per_cycle)
     return status.SUCCESS, spec
Example #29
0
 async def get_specification(self, timeout: float = 0.5, reset_cached=False)\
         -> Optional[Specification]:
     if reset_cached:
         self.specification = None
     if self.specification:
         return self.specification
     request = api.Message()
     request.engine.specification_req = True
     if not self.send(message=request):
         return None
     response, _ = await self.wait_message(timeout=timeout)
     if not response:
         return None
     spec = api.get_message_field(response, ["engine", "specification"])
     if not spec:
         return None
     self.specification = Specification(max_thrust=spec.max_thrust)
     return self.specification
Example #30
0
    async def get_blueprints_list(self,
                                  start_with: str = "",
                                  timeout: float = 0.5) -> (Status, List[str]):
        request = api.Message()
        request.blueprints_library.blueprints_list_req = start_with
        if not self.send(request):
            return Status.FAILED_TO_SEND_REQUEST, []

        names: List[str] = []
        done = False
        while not done:
            response, _ = await self.wait_message(timeout=timeout)
            if not response:
                return Status.RESPONSE_TIMEOUT, []
            response = api.get_message_field(
                response, ["blueprints_library", "blueprints_list"])
            if not response:
                return Status.UNEXPECTED_RESPONSE, []
            names.extend(response.names)
            done = response.left == 0
        return Status.SUCCESS, names