async def get_content(self, timeout: float = 0.5) -> \
         Tuple[Status, Optional[Content]]:
     request = api.Message()
     request.resource_container.content_req = True
     if not self.send(message=request):
         return ResourceContainerI.Status.FAILED_TO_SEND_REQUEST, None
     return await self.wait_content(timeout)
예제 #2
0
 async def time(self, timeout: float = 0.1) -> Optional[int]:
     """Return current server time"""
     request = api.Message()
     request.system_clock.time_req = True
     if not self.send(message=request):
         return None
     return await self.wait_timestamp()
예제 #3
0
 async def get_state(self) -> Optional[State]:
     """Return current ship's state"""
     request = api.Message()
     request.ship.state_req = True
     if not self.send(message=request):
         return None
     return await self.wait_state()
예제 #4
0
    async def open_tunnel(self, port: int) -> Tuple[Status, Optional[int]]:
        """Open tunnel to the specified 'port'. Return (sessionId, None) on
        success, otherwise return (None, error)"""
        request = api.Message()
        request.commutator.open_tunnel = port
        self.send(request)

        # it shouldn't take much time
        response, _ = await self.wait_message(timeout=0.1)
        if not response:
            return CommutatorI.Status.RESPONSE_TIMEOUT, None
        # Note: once 'open_tunnel_report' is passed through 'sessions_mux',
        # it creates a new related session object, that can be retreived by
        # 'get_channel_for_session()'
        tunnel_id = get_message_field(response,
                                      ["commutator", "open_tunnel_report"])
        if tunnel_id is None:
            error = get_message_field(response,
                                      ["commutator", "open_tunnel_failed"])
            if not error:
                return CommutatorI.Status.UNEXPECTED_RESPONSE, None
            self._logger.warning(
                f"Failed to open tunnel to port #{port}: {error}")
            return CommutatorI.Status.convert(error), None
        return CommutatorI.Status.SUCCESS, tunnel_id
예제 #5
0
 async def monitor(self, duration_ms: int) -> Optional[State]:
     """Start ship's state monitoring. Return current state.
     After this call you may use 'wait_state()' to receive updates
     """
     request = api.Message()
     request.ship.monitor = duration_ms
     if not self.send(message=request):
         return None
     return await self.wait_state()
예제 #6
0
 async def start_build(self, blueprint: str, ship_name: str) -> Status:
     request = api.Message()
     req_body = request.shipyard.start_build
     req_body.blueprint_name = blueprint
     req_body.ship_name = ship_name
     if not self.send(message=request):
         return ShipyardI.Status.FAILED_TO_SEND_REQUEST
     status, _ = await self.wait_building_report()
     return status
예제 #7
0
 async def get_total_slots(self) -> (bool, int):
     """Return total number of devices, attached to this commutator"""
     request = api.Message()
     request.commutator.total_slots_req = True
     self.send(request)
     response, _ = await self.wait_message()
     if not response:
         return False, 0
     total_slots = get_message_field(response,
                                     ["commutator", "total_slots"])
     return total_slots is not None, total_slots
 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
예제 #9
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"])
 async def monitor(self,
                   timeout: float = 0.5
                   ) -> Tuple[Status, Optional[Content]]:
     """Start monitoring session.
     Note: monitoring session can't be closed. The only way to stop
     monitoring session is close the channel.
     """
     request = api.Message()
     request.resource_container.monitor = True
     if not self.send(message=request):
         return ResourceContainerI.Status.FAILED_TO_SEND_REQUEST, None
     return await self.wait_content(timeout)
예제 #11
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"])
예제 #12
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)
예제 #13
0
 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)
예제 #14
0
 async def monitoring(self,
                      interval_ms: int,
                      timeout: float = 0.5) -> Optional[int]:
     """Start monitoring in this session and return current time.
     Server will send current timestamp in this session every 'interval_ms'
     milliseconds. You may call 'wait_timestamp()' with
     timeout=interval_ms*5 in order to receive timestamps.
     Note: the only way to stop monitoring is to close the session.
     """
     request = api.Message()
     request.system_clock.monitor = interval_ms
     if not self.send(message=request):
         return None
     return await self.wait_timestamp()
예제 #15
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
 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)
예제 #17
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)
예제 #18
0
    async def close_tunnel(self, tunnel_id: int) -> Status:
        request = api.Message()
        request.commutator.close_tunnel = tunnel_id
        self.send(request)

        # it shouldn't take much time
        response, _ = await self.wait_message(timeout=0.2)
        if not response:
            return CommutatorI.Status.RESPONSE_TIMEOUT

        status = get_message_field(response,
                                   ["commutator", "close_tunnel_status"])
        if status is None:
            return CommutatorI.Status.UNEXPECTED_RESPONSE
        return CommutatorI.Status.convert(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)
예제 #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)
예제 #21
0
    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)
    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
예제 #23
0
 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)
예제 #24
0
 async def get_module_info(self, slot_id: int)\
         -> Optional[ModuleInfo]:
     """Return information about module, installed into the specified
     'slot_id'.
     """
     request = api.Message()
     request.commutator.module_info_req = slot_id
     self.send(request)
     response, _ = await self.wait_message()
     if not response:
         return None
     module_info = get_message_field(response,
                                     ["commutator", "module_info"])
     if not module_info:
         return None
     info = ModuleInfo.from_protubuf(module_info)
     return info
예제 #25
0
 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
예제 #26
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
예제 #27
0
    async def get_all_modules(self) -> Optional[List[ModuleInfo]]:
        """Return all modules, attached to commutator. Modules received will
        be stored to a local cache"""
        success, total_slots = await self.get_total_slots()
        if not success:
            return None
        request = api.Message()
        request.commutator.all_modules_info_req = True
        self.send(request)

        result: List[ModuleInfo] = []
        for i in range(total_slots):
            response, _ = await self.wait_message()
            module_info = get_message_field(response,
                                            ["commutator", "module_info"])
            if not module_info:
                return None
            result.append(ModuleInfo.from_protubuf(module_info))
        return result
    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))
예제 #29
0
 async def set_thrust(self,
                      thrust: Vector,
                      at: int = 0,
                      duration_ms: int = 0) -> bool:
     """Set engine thrust to the specified 'thrust' for the
     specified 'duration_ms' milliseconds. If 'duration_ms' is 0, then
     the thrust will be set until another command.
     Function doesn't await any acknowledgement or response.
     Return true if a request has been sent
     """
     request = api.Message()
     if at:
         request.timestamp = at
     thrust_req = request.engine.change_thrust
     thrust_req.x = thrust.x
     thrust_req.y = thrust.y
     thrust_req.thrust = int(thrust.abs())
     thrust_req.duration_ms = duration_ms
     return self.channel.send(message=request)
예제 #30
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