예제 #1
0
    def get():
        """Logic for GET events. Returns the current episode ID and log content"""

        req_args = utils.parse_args(_PARSER)
        close_ep = req_args.get("close_ep", False)

        if not in_agent_mode():
            return responses.bad_request_resp(
                "Episode data only recorded when in Agent mode")

        ep_file_path = bb_logging.EP_FILE

        if not ep_file_path:
            return responses.bad_request_resp("No episode being recorded")

        if close_ep:
            err = utils.sim_proxy().simulation.reset()
            if err:
                return responses.internal_err_resp(
                    f"Couldn't reset simulation: {err}")

        if not ep_file_path.exists():
            return responses.internal_err_resp("Could not find episode file")

        lines = list(line.rstrip("\n") for line in open(ep_file_path))

        data = {
            "cur_ep_id": bb_logging.EP_ID,
            "cur_ep_file": str(ep_file_path.absolute()),
            "log": lines,
        }

        return responses.ok_resp(data)
예제 #2
0
파일: siminfo.py 프로젝트: rkm/bluebird
    def get():

        sim_props = utils.sim_proxy().simulation.properties
        if not isinstance(sim_props, SimProperties):
            return responses.internal_err_resp(
                f"Couldn't get the sim properties: {sim_props}")

        callsigns = utils.sim_proxy().aircraft.callsigns
        if not isinstance(callsigns, list):
            return responses.internal_err_resp(
                f"Couldn't get the callsigns: {callsigns}")

        data = {
            "callsigns": [str(x) for x in callsigns],
            "dt": sim_props.dt,
            "mode": Settings.SIM_MODE.name,
            "scenario_name": sim_props.scenario_name,
            "scenario_time": sim_props.scenario_time,
            "sector_name": sim_props.sector_name,
            "seed": sim_props.seed,
            "sim_type": Settings.SIM_TYPE.name,
            "speed": sim_props.speed,
            "state": sim_props.state.name,
            "utc_datetime": str(sim_props.utc_datetime),
        }

        return responses.ok_resp(data)
예제 #3
0
    def get():
        """
        Logic for GET events. If the request contains an identifier to an existing
        aircraft, then information about its route (FMS flightplan) is returned
        """

        req_args = utils.parse_args(_PARSER)
        callsign = req_args[utils.CALLSIGN_LABEL]

        resp = utils.check_exists(utils.sim_proxy(), callsign)
        if resp:
            return resp

        route_info = utils.sim_proxy().aircraft.route(callsign)

        if not isinstance(route_info, tuple):
            if route_info == "Aircraft has no route":
                return responses.bad_request_resp(route_info)
            return responses.internal_err_resp(route_info)

        data = {
            utils.CALLSIGN_LABEL: str(callsign),
            "route_name": route_info[0],
            "next_waypoint": route_info[1],
            "route_waypoints": route_info[2],
        }
        return responses.ok_resp(data)
예제 #4
0
    def get():
        """Logic for GET events. Returns properties for the specified aircraft"""

        req_args = utils.parse_args(_PARSER)
        callsign = req_args[utils.CALLSIGN_LABEL]

        sim_props = utils.sim_proxy().simulation.properties
        if not isinstance(sim_props, SimProperties):
            return responses.internal_err_resp(sim_props)

        if callsign:
            resp = utils.check_exists(utils.sim_proxy(), callsign)
            if resp:
                return resp

            props = utils.sim_proxy().aircraft.properties(callsign)
            if not isinstance(props, AircraftProperties):
                return internal_err_resp(props)

            data = utils.convert_aircraft_props(props)
            data.update({"scenario_time": sim_props.scenario_time})

            return responses.ok_resp(data)

        # else: get_all_properties

        props = utils.sim_proxy().aircraft.all_properties
        if isinstance(props, str):
            return responses.internal_err_resp(
                f"Couldn't get the aircraft properties: {props}")
        if not props:
            return responses.bad_request_resp("No aircraft in the simulation")

        data = {}
        for prop in props.values():
            data.update(utils.convert_aircraft_props(prop))
        data["scenario_time"] = sim_props.scenario_time

        return responses.ok_resp(data)
예제 #5
0
    def post():
        """Shuts down the BlueBird server"""

        req_args = utils.parse_args(_PARSER)

        sim_quit = utils.sim_proxy().shutdown(
            shutdown_sim=bool(req_args["stop_sim"]))
        sim_quit_msg = f"(Sim shutdown ok = {sim_quit})"

        # TODO Check we still get a response before this executes. If not, need to set
        # this to fire on a timer
        try:
            shutdown_fn = request.environ.get("werkzeug.server.shutdown")
            if not shutdown_fn:
                return responses.internal_err_resp(
                    f"No shutdown function available. {sim_quit_msg}")
            shutdown_fn()
        except Exception as exc:
            return responses.internal_err_resp(
                f"Could not shutdown: {exc}. {sim_quit_msg}")

        data = f"BlueBird shutting down! {sim_quit_msg}"
        return responses.ok_resp(data)
예제 #6
0
    def get():
        """Returns the sector defined in the current simulation"""

        sector: SectorWrapper = utils.sim_proxy().simulation.sector

        if not sector:
            return responses.bad_request_resp("No sector has been set")

        # TODO (RKM 2019-12-20) Check what exceptions this can throw
        try:
            geojson_str = geojson.dumps(sector.element)
        except Exception as exc:
            return responses.internal_err_resp(f"Couldn't get sector geojson: {exc}")

        return responses.ok_resp({"name": sector.name, "content": geojson_str})
예제 #7
0
파일: utils.py 프로젝트: rkm/bluebird
def check_exists(sim_proxy: SimProxy,
                 callsign: types.Callsign,
                 negate: bool = False) -> Optional[Response]:
    """Checks if an aircraft exists, and returns an appropriate response if not"""

    exists = sim_proxy.aircraft.exists(callsign)
    if not isinstance(exists, bool):
        return responses.internal_err_resp(
            f"Could not check if the aircraft exists: {exists}")
    if not exists and not negate:
        return responses.bad_request_resp(
            f'Aircraft "{callsign}" does not exist')
    if exists and negate:
        return responses.bad_request_resp(
            f'Aircraft "{callsign}" already exists')
    return None
예제 #8
0
    def post():
        """
        Logic for POST events. Returns the simulator to a previous state given a logfile
        :return:
        """

        if Settings.SIM_MODE != SimMode.Agent:
            return responses.bad_request_resp("Can only be used in agent mode")

        if Settings.SIM_TYPE != SimType.BlueSky:
            return responses.bad_request_resp(
                f"Method not supported for the {Settings.SIM_TYPE} simulator")

        req_args = parse_args(_PARSER)

        if bool(req_args["filename"]) == bool(req_args["lines"]):
            return responses.bad_request_resp(
                "Either filename or lines must be specified")

        target_time = req_args["time"]
        if target_time <= 0:
            return responses.bad_request_resp(
                "Target time must be greater than 0")

        props = sim_proxy().simulation.properties
        if isinstance(props, str):
            return responses.internal_err_resp(
                f"Could not get the sim properties: {props}")

        prev_dt = props.dt

        _LOGGER.debug("Starting log reload")

        # Reset now so the current episode log is closed
        err = sim_proxy().simulation.reset()

        if err:
            return responses.internal_err_resp(f"Simulation not reset: {err}")

        if req_args["filename"]:
            log_path = Path(os.getcwd(), req_args["filename"])
            if not log_path.exists():
                return responses.bad_request_resp(
                    f'Could not find episode file {req_args["filename"]}')
            with open(req_args["filename"]) as log_file:
                lines = list(log_file)
        else:
            lines = req_args["lines"]

        _LOGGER.debug("Parsing log content")
        parsed_scn = parse_lines(lines, target_time)

        if isinstance(parsed_scn, str):
            return responses.bad_request_resp(
                f"Could not parse episode content: {parsed_scn}")

        # TODO Move regex to outer scope and comment
        # Assert that the requested time is not past the end of the log
        last_data = next(x for x in reversed(lines)
                         if re.match(r".*A \[(\d+)\] (.*)$", x))
        last_time = int(re.search(r"\[(.*)]", last_data).group(1))

        if target_time > last_time:
            return responses.bad_request_resp(
                "Error: Target time was greater than the latest time in the log"
            )

        # err = validate_scenario(parsed_scn["lines"])

        if err:
            return responses.bad_request_resp(
                "Could not create a valid scenario from the given log")

        # All good - do the reload

        _LOGGER.debug("Setting the simulator seed")
        err = sim_proxy().simulation.set_seed(int(parsed_scn["seed"]))

        if err:
            return responses.internal_err_resp(f"Could not set seed {err}")

        scn_name = f"reloads/{str(uuid.uuid4())[:8]}.scn"

        _LOGGER.debug("Uploading the new scenario")
        # store_local_scn(scn_name, parsed_scn["lines"])
        err = sim_proxy().simulation.upload_new_scenario(
            scn_name, parsed_scn["lines"])

        if err:
            return responses.internal_err_resp(
                f"Error uploading scenario: {err}")

        _LOGGER.info("Starting the new scenario")
        err = sim_proxy().simulation.load_scenario(scn_name, start_paused=True)

        if err:
            return responses.internal_err_resp(
                f"Could not start scenario after upload {err}")

        props = sim_proxy().simulation.properties
        if isinstance(props, str):
            return responses.internal_err_resp(
                f"Could not get the sim properties: {props}")

        diff = target_time - props.scenario_time

        if diff:
            # Naive approach - set DTMULT to target, then STEP once...
            _LOGGER.debug(
                f"Time difference is {diff}. Stepping to {target_time}")
            err = sim_proxy().simulation.set_speed(diff)
            if err:
                return responses.internal_err_resp(
                    f"Could not change speed: {err}")

            _LOGGER.debug("Performing step")
            err = sim_proxy().simulation.step()

            if err:
                return responses.internal_err_resp(
                    f"Could not step simulations: {err}")

        else:
            _LOGGER.debug("Simulation already at required time")

        # Reset DTMULT to the previous value
        err = sim_proxy().simulation.set_speed(prev_dt)
        if err:
            return responses.internal_err_resp(
                "Episode reloaded, but could not reset DTMULT to previous value"
            )

        # TODO Do we want to check before/after positions here and check if the
        # differences are acceptable?

        return responses.ok_resp()