def set_mandatory_update_status():
    """API to save the mandatory update status to the software update status file.

    Returns:
        dict: Execution status if the API call was successful.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    update_completed_value = request.json.get("update_completed")
    if update_completed_value is None:
        return jsonify({
            "success": False,
            "reason": "Status must be a boolean"
        })
    webserver_node.get_logger().info(
        "Setting mandatory software update status to "
        f"{update_completed_value}")

    software_update_status = {"update_completed": update_completed_value}
    try:
        with open(SOFTWARE_UPDATE_STATUS_PATH,
                  "w") as software_update_status_file:
            json.dump(software_update_status, software_update_status_file)
        return jsonify({"success": True})
    except IOError:
        webserver_node.get_logger().error(
            "Unable to set software update status: "
            f"{software_update_status}")
        return jsonify({"success": False})
Пример #2
0
def get_battery_level():
    """API to call the service to get the current vehicle battery level
       information.

    Returns:
        dict: Execution status if the API call was successful, vehicle
              battery level details and error reason if call fails.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()

    try:
        battery_level_req = BatteryLevelSrv.Request()
        battery_level_res = call_service_sync(webserver_node.battery_level_cli,
                                              battery_level_req)
        if battery_level_res:
            data = {"battery_level": battery_level_res.level, "success": True}
            webserver_node.get_logger().info(
                f"Battery Level: {data['battery_level']}")
            return jsonify(data)
        else:
            return jsonify(success=False, reason="Error")
    except Exception as ex:
        webserver_node.get_logger().error(
            f"Unable to reach battery level server: {ex}")
        return jsonify(success=False, reason="Error")
Пример #3
0
def is_ssh_default_password_changed():
    """API called to check if the default password for SSH is changed.
       This will populate the ssh enabled radio button in the UI.

    Returns:
        dict: Execution status if the API call was successful, flag to indicate
              if default ssh password is changed and with error reason if
              call fails.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    webserver_node.get_logger().info("Providing ssh enabeld as response")
    try:
        # Authenticate against default password
        if pam.pam().authenticate(DEFAULT_USER, DEFAULT_SSH_PASSWORD):
            return jsonify(success=True,
                           isDefaultSshPasswordChanged=False,
                           reason="Default password not changed")
        else:
            return jsonify(success=True,
                           isDefaultSshPasswordChanged=True,
                           reason="Default password changed")
    except Exception as ex:
        webserver_node.get_logger().error(
            f"Failed check if the ssh password is default: {ex}")
        return jsonify(success=False,
                       isDefaultSshPasswordChanged=False,
                       reason="Error")
Пример #4
0
def get_sensor_status():
    """Helper function to call the service to get the status of the sensor connected to the vehicle.

    Returns:
        tuple: A tuple with error code and SensorStatusCheckSrv.Response object.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    try:
        sensor_status_req = SensorStatusCheckSrv.Request()
        sensor_status_res = call_service_sync(webserver_node.sensor_status_cli,
                                              sensor_status_req)
        if sensor_status_res and sensor_status_res.error == 0:
            webserver_node.get_logger().info(
                "Verify required sensor status: "
                f"Camera status: {sensor_status_res.single_camera_status}, "
                f"Stereo status: {sensor_status_res.stereo_camera_status}, "
                f"Lidar status: {sensor_status_res.lidar_status}")
            return 0, sensor_status_res
        else:
            webserver_node.get_logger().error(
                "Failed to call the sensor status service")
            return 1, {}
    except Exception as ex:
        webserver_node.get_logger().error(
            f"Unable to reach sensor status server: {ex}")
        return 1, {}
Пример #5
0
def api_wifi_information():
    """API to get the list of available WiFi networks. This will populate the
       wifi drop down in the UI.

    Returns:
        list: List of dict objects with WiFi network details.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    webserver_node.get_logger().info("Providing wifi information as response")
    ssid_set = set()
    cmd = "/usr/bin/nmcli -t -f ssid,signal,security -e no device wifi list"
    wifi_list = list()
    wifi_lines = utility.execute(cmd, shlex_split=True)[1].split("\n")
    for wifi in wifi_lines:
        words = wifi.split(":")
        if words[0] in ssid_set or words[0] == "--" or len(words[0]) == 0:
            continue
        ssid_set.add(words[0])

        wifi_data = {
            "ssid": words[0],
            "strength": math.floor(1.0 + float(words[1]) / 30.0),
            "security_info": words[2]
        }
        wifi_list.append(wifi_data)
    return jsonify(wifi_list)
Пример #6
0
def read_model_metadata_file(model_metatdata_file):
    """Helper method that reads the model metadata file for the model selected and validates
       the sensor configuration.

    Args:
        model_metatdata_file (str): Path to the model_metadata file.

    Returns:
        tuple: A tuple of error code, error message and the JSON data
               with the content read from model_metadata.json of the model.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    try:
        if (not os.path.isfile(model_metatdata_file)):
            webserver_node.get_logger().error(
                f"No model_metadata_file: {model_metatdata_file}.")
            # return 1 which means model_metadata file is not found
            return 1, "No model_metadata_file for the model selected", {}
        with open(model_metatdata_file) as json_file:
            data = json.load(json_file)

        return 0, "", data
    except Exception as ex:
        webserver_node.get_logger().error(
            f"Error while reading model_metadata.json: {ex}")
        return 1, "Error while reading model_metadata.json", {}
Пример #7
0
def api_manual_drive():
    """API that publishes control messages to control the angle and throttle in
       manual drive mode.

    Returns:
        dict: Execution status if the API call was successful.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    angle = request.json.get("angle")
    throttle = request.json.get("throttle")
    max_speed = request.json.get("max_speed")

    if angle is None:
        return api_fail("angle is required")
    if throttle is None:
        return api_fail("throttle is required")
    if max_speed is None:
        return api_fail("max_speed is required")

    if angle < -1.0 or angle > 1.0:
        return api_fail("angle out of range")
    if throttle < -1.0 or throttle > 1.0:
        return api_fail("throttle out of range")

    webserver_node.get_logger().info(f"Angle: {angle}  Throttle: {throttle}")

    # Create the servo message.
    msg = ServoCtrlMsg()
    # bound the throttle value based on the categories defined
    msg.angle = -1.0 * get_categorized_manual_angle(angle)
    categorized_throttle = get_categorized_manual_throttle(throttle)
    msg.throttle = -1.0 * get_rescaled_manual_speed(categorized_throttle,
                                                    max_speed)
    webserver_node.pub_manual_drive.publish(msg)
    return jsonify({"success": True})
Пример #8
0
def api_set_start_stop():
    """API to call the enable_state service to start and stop the vehicle.

    Returns:
        dict: Execution status if the API call was successful and error
              reason if failed.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    start_stop = request.json.get("start_stop")
    if start_stop is None:
        return jsonify({"success": False, "reason": "start_stop must be set."})

    webserver_node.get_logger().info(
        f"Changed the enable state to {start_stop}")
    start_stop_state = False if start_stop == "stop" else True
    try:
        enable_state_req = EnableStateSrv.Request()
        enable_state_req.is_active = start_stop_state
        enable_state_res = call_service_sync(webserver_node.enable_state_cli,
                                             enable_state_req)
        if enable_state_res and (enable_state_res.error == 0):
            return jsonify({"success": True})
        else:
            return jsonify({"success": False, "reason": "Error"})

    except Exception as ex:
        webserver_node.get_logger().error(
            f"Unable to reach enable state server: {ex}")
        return jsonify({
            "success": False,
            "reason": "Unable to reach enable state server."
        })
Пример #9
0
def is_usb_connected():
    """API to return information if the DeepRacer vehicle is connected the micro-USB cable to
       laptop/computer.

    Returns:
        [type]: True if the vehicle is connected to USB
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    is_usb_connected = False
    conn_res = check_usb_connection()
    usb_connected = True if conn_res["success"] and conn_res[
        "is_usb_connected"] else False
    if request.headers["Referer"].find(
            "deepracer.aws") != -1 and usb_connected:
        is_usb_connected = True

    webserver_node.get_logger().info(
        f"host: {request.headers['Referer']} "
        f"otg_connected: {'connected' if usb_connected else 'not connected'} "
        f"is_usb_connected: {'connected' if is_usb_connected else 'not connected'}"
    )

    return jsonify({
        "success": True,
        "is_usb_connected": is_usb_connected,
    })
Пример #10
0
def is_ssh_enabled():
    """API called to execute commands to check if SSH is enabled.
       This will populate the ssh enabled radio button in the UI.

    Returns:
        dict: Execution status if the API call was successful, flag to indicate
              if ssh is enabled and with error reason if call fails.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    webserver_node.get_logger().info("Providing ssh enabled as response")
    try:
        # Check SSH status
        if utility.execute("/bin/systemctl --no-pager status ssh",
                           shlex_split=True)[1].find("active (running)") > -1:
            # Check UFW status
            stdout = utility.execute("/usr/sbin/ufw status",
                                     shlex_split=True)[1]
            if re.search("22.*ALLOW", stdout):
                return jsonify(success=True,
                               isSshEnabled=True,
                               reason="Ssh is enabled.")
            else:
                return jsonify(success=True,
                               isSshEnabled=False,
                               reason="Ssh not enabled.")
        else:
            return jsonify(success=True,
                           isSshEnabled=False,
                           reason="Ssh not enabled.")
    except Exception as ex:
        webserver_node.get_logger().error(
            f"Failed check if ssh is enabled: {ex}")
        return jsonify(success=False, isSshEnabled=False, reason="Error")
def execute(cmd, input_str=None, shell=False, shlex_split=False):
    """Execute the commands on shell terminal.

    Args:
        cmd (str): Command to be executed.
        input_str (str, optional): Input string that has to be passed
                                   to the shell input. Defaults to None.
        shell (bool, optional): Specifies whether to use the shell as the
                                program to execute. Defaults to False.
        shlex_split(bool, optional): Specifies whether to split the command.
                                     Defaults to False.
    Returns:
        tuple: A tuple of return code and the output of the command.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    webserver_node.get_logger().info(f"Command executing: {cmd}")
    if shlex_split:
        cmd = shlex.split(cmd)
    proc = Popen(cmd,
                 stdout=PIPE,
                 stdin=PIPE,
                 stderr=STDOUT,
                 universal_newlines=True,
                 shell=shell)
    stdout = proc.communicate(input=input_str)[0]

    webserver_node.get_logger().info(f"{cmd} : execute output: {stdout}")

    return proc.returncode, stdout
def is_network_inactive(ssid):
    """Check if the supplied SSID is currently not connected, but previously connected.

    Args:
        ssid (str): SSID value.

    Returns:
        bool: True if the SSID is inactive else False.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    webserver_node.get_logger().info(f"Checking if ssid: {ssid} is inactive")

    is_present = False

    stdout = execute("/usr/bin/nmcli -t -f name -e no con show",
                     shlex_split=True)[1]
    for line in stdout.splitlines():
        if line == ssid:
            is_present = True
            break

    if is_present and not is_network_connected(ssid):
        return True

    return False
def begin_software_update():
    """API to call the service to begin the software update process.

    Returns:
        dict: Execution status if the API call was successful and error reason if failed.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    try:
        webserver_node.get_logger().info("Started software update.")
        begin_sw_update_req = BeginSoftwareUpdateSrv.Request()
        begin_sw_update_req.sleep_time_before_reboot = SLEEP_TIME_BEFORE_REBOOT
        begin_sw_update_res = call_service_sync(
            webserver_node.begin_sw_update_cli, begin_sw_update_req)
        if begin_sw_update_res and begin_sw_update_res.response_status:
            return jsonify({"success": True})
        else:
            webserver_node.get_logger().error(
                "Begin software update service call failed")
            return jsonify({
                "success": False,
                "reason": "Update service call failed"
            })
    except Exception as ex:
        webserver_node.get_logger().error(
            f"Unable to reach begin update server: {ex}")
        return jsonify({
            "success": False,
            "reason": "Unable to reach begin update server"
        })
Пример #14
0
def control_modes_available():
    """API to call the GetCtrlModesCountSrv service to get the list of available modes
       in ctrl_pkg (autonomous/manual/calibration/followtheleader).

    Returns:
        dict: Execution status if the API call was successful, list of available modes
              and error reason if call fails.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    webserver_node.get_logger().info("Providing the number of available modes")
    try:
        get_ctrl_modes_req = GetCtrlModesSrv.Request()
        get_ctrl_modes_res = call_service_sync(
            webserver_node.get_ctrl_modes_cli, get_ctrl_modes_req)

        control_modes_available = list()
        for mode in get_ctrl_modes_res.modes:
            control_modes_available.append(constants.MODE_DICT[mode])

        data = {
            "control_modes_available": control_modes_available,
            "success": True
        }
        return jsonify(data)

    except Exception as ex:
        webserver_node.get_logger().error(
            f"Unable to reach get ctrl modes service: {ex}")
        return jsonify(success=False, reason="Error")
def api_adjust_calibrating_wheels(cali_type):
    """API to call the service to publishes a message withPWM measurement to adjust
       wheels while calibrating.

    Args:
        cali_type (int): Calibration type identifying steering/throttle calibration.

    Returns:
        dict: Execution status if the API call was successful.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    form_data = request.json
    if cali_type == "angle":
        angle = float(
            int(form_data["pwm"]) * PWM_ANGLE_CONVERSION + PWM_OFFSET)
        throttle = -1.0
    else:
        angle = -1.0
        throttle = float(
            int(form_data["pwm"]) * PWM_THROTTLE_CONVERSION + PWM_OFFSET)
    webserver_node.get_logger().info(f"Angle: {angle}  Throttle: {throttle}")
    msg = ServoCtrlMsg()
    msg.angle = angle
    msg.throttle = throttle
    webserver_node.pub_calibration_drive.publish(msg)
    return jsonify({"success": True})
def set_calibration_mode():
    """API to call the service to activate calibration mode.

    Returns:
        dict: Execution status if the API call was successful.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    try:
        vehicle_state_req = ActiveStateSrv.Request()
        vehicle_state_req.state = CALIBRATION_MODE
        vehicle_state_res = call_service_sync(webserver_node.vehicle_state_cli,
                                              vehicle_state_req)

        enable_state_req = EnableStateSrv.Request()
        enable_state_req.is_active = True
        enable_state_res = call_service_sync(webserver_node.enable_state_cli,
                                             enable_state_req)

        success = (vehicle_state_res and vehicle_state_res.error == 0
                   and enable_state_res and enable_state_res.error == 0)
        if not success:
            webserver_node.get_logger().error(
                "Vehicle state service call failed")
            return jsonify(success=False, reason="Error")
        return jsonify(success=True)
    except Exception as ex:
        webserver_node.get_logger().error(
            f"Unable to reach vehicle state server: {ex}")
        return jsonify(success=False, reason="Error")
Пример #17
0
def api_get_logs(log_type, num_lines):
    """API to return the logs of appropriate type and logging window based on
       user selection.

    Args:
        log_type (str): Log type attribute name pointing to the log file location.
                        Defined in the constants file.
        num_lines (int): Number of latest log lines to return.

    Returns:
        dict: Execution status if the API call was successful and the
              log file read response.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    num_lines = 1000 if num_lines > 1000 else num_lines
    log_content = ""
    try:
        with VEHICLE_LOGS_BLUEPRINT.open_resource(getattr(
                constants, log_type)) as logfile:
            lines = logfile.readlines()[-num_lines:]
            for i in range(0, len(lines)):
                log_content = log_content + lines[i].decode("utf-8")
    except AttributeError:
        webserver_node.get_logger().error("Type of log does not exist!")
        log_content = "Type of log does not exist!"
    except IOError:
        webserver_node.get_logger().error("File Not Found!")
        log_content = "File Not Found!"
    return jsonify({"success": True, "data": log_content})
Пример #18
0
def get_device_info():
    """API to call the service to get the current hardware version of the
       DeepRacer vehicle and the software version of aws-deepracer-core package.

    Returns:
        dict: Execution status if the API call was successful, hardware and
              software version details and error reason if call fails.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    webserver_node.get_logger().info(
        "Providing hardware and software revision "
        "details as response")
    try:
        get_revision_info_req = GetDeviceInfoSrv.Request()
        get_revision_info_res = call_service_sync(
            webserver_node.get_revision_info_cli, get_revision_info_req)
        if get_revision_info_res and get_revision_info_res.error == 0:
            data = {
                "hardware_version": get_revision_info_res.hardware_version,
                "software_version": get_revision_info_res.software_version,
                "success": True
            }
            webserver_node.get_logger().info(
                f"Hardware version: {data['hardware_version']}, "
                f"Software version: {data['software_version']}")
        else:
            webserver_node.get_logger().error(
                "Get device info service call failed")
            data = {"reason": "Error", "success": False}
        return jsonify(data)

    except Exception as ex:
        webserver_node.get_logger().error(
            f"Unable to reach revision info server: {ex}")
        return jsonify(success=False, reason="Error")
def update_password_api():
    """API that updates the console password to the new one sent as a parameter.

    Returns:
        dict: Execution status if the API call was successful, flag to indicate
              if password update was successful and error reason if call fails.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()

    old_password = request.json.get("old_password").encode("utf-8")
    new_password = request.json.get("new_password").encode("utf-8")

    try:
        with open(PASSWORD_PATH, "r") as pwd_file:
            password_digest = pwd_file.readline()

        if hmac.compare_digest(compute_password_digest(old_password), password_digest):
            with open(PASSWORD_PATH, "w") as pwd_file:
                pwd_file.write(compute_password_digest(new_password))
                pwd_file.close()
            return jsonify({"success": True})
        else:
            return jsonify({"success": False,
                            "reason": "The password is incorrect. Provide your current password."})
    except IOError:
        webserver_node.get_logger().error("Password.txt not found in given path")
        return jsonify({"success": False, "reason": "Password.txt not found."})
Пример #20
0
def max_nav_throttle():
    """API to call the navigation_throttle service to set the throttle scale in the
       autonomous mode.

    Returns:
        dict: Execution status if the API call was successful and error
              reason if failed.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    nav_throttle = request.json.get("throttle")
    if nav_throttle is None:
        return jsonify({"success": False, "reason": "value must be set."})
    webserver_node.get_logger().info(
        f"Setting max navigation throttle to {nav_throttle}")
    try:
        set_throttle_req = NavThrottleSrv.Request()
        set_throttle_req.throttle = nav_throttle / constants.MAX_AUTO_THROTTLE_VAL
        set_throttle_res = call_service_sync(webserver_node.set_throttle_cli,
                                             set_throttle_req)
        if set_throttle_res and (set_throttle_res.error == 0):
            return jsonify({"success": True})
        else:
            return jsonify(
                success=False,
                reason="Failed to call the navigation throttle service")
    except Exception as ex:
        webserver_node.get_logger().error(
            f"Unable to reach navigation throttle server: {ex}")
        return jsonify(success=False,
                       reason="Unable to reach navigation throttle server")
def get_software_update_status():
    """API to stream the software update progress percentage and the current state.

    Returns:
        flask.Response: Flask response object with the content_type set to text/event-stream.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    webserver_node.get_logger().info("Inside the update status function")

    def events():
        webserver_node.get_logger().info(
            "Running software update event source")
        for i, c in enumerate(itertools.cycle("\|/-")):
            try:
                pct_dict = webserver_node.pct_dict_db.get_nowait()
                percentage_completion = pct_dict["update_pct"]
                result = f"status:{pct_dict['status']}|update_pct:{percentage_completion}"
                yield "data: %s %d\n\n" % (result, i)
                # The sleep is introduced here so as to fetch the next message from
                # the software_update_status service. This is rate at which the UI shows
                # the change in the status querying the service. So this will provide us
                # to control the rate at which we would like to see the software update
                # information on the browser. For now its set to 1 seconds.
                time.sleep(SOFTWARE_UPDATE_FETCH_FREQUENCY)
            except Exception as ex:
                webserver_node.get_logger().error(
                    f"Unable to reach update status service: {ex}")
                result = "status:checking|update_pct:0"
                yield f"data: {result} {1}\n\n"
                break

    return Response(events(), content_type="text/event-stream")
Пример #22
0
def max_ftl_speed():
    """API to call the SetMaxSpeedSrv service to set the throttle scale in the
       followtheleader mode.

    Returns:
        dict: Execution status if the API call was successful and error
              reason if failed.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    ftl_speed = request.json.get("throttle")
    if ftl_speed is None:
        return jsonify({"success": False, "reason": "value must be set."})
    webserver_node.get_logger().info(f"Setting max ftl speed to {ftl_speed}%")
    try:
        set_speed_req = SetMaxSpeedSrv.Request()
        set_speed_req.max_speed_pct = float(ftl_speed / 100)
        set_speed_res = call_service_sync(webserver_node.set_ftl_max_speed_cli,
                                          set_speed_req)
        if set_speed_res and (set_speed_res.error == 0):
            return jsonify({"success": True})
        else:
            return jsonify(success=False,
                           reason="Failed to call the SetMaxSpeed service")
    except Exception as ex:
        webserver_node.get_logger().error(
            f"Unable to reach SetMaxSpeed server: {ex}")
        return jsonify(success=False,
                       reason="Unable to reach SetMaxSpeed server")
Пример #23
0
def api_set_drive_mode():
    """API to toggle the drive mode between Autonomous/Manual mode.

    Returns:
        dict: Execution status if the API call was successful and error
              reason if failed.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    drive_mode = request.json.get("drive_mode")
    if drive_mode is None:
        return jsonify({"success": False, "reason": "drive_mode must be set."})

    webserver_node.get_logger().info(f"Changed the vehicle state to {drive_mode}")
    drive_mode_state = 0 if drive_mode == "manual" else 1

    try:
        vehicle_state_req = ActiveStateSrv.Request()
        vehicle_state_req.state = drive_mode_state
        vehicle_state_res = call_service_sync(webserver_node.vehicle_state_cli,
                                              vehicle_state_req)
        if vehicle_state_res and (vehicle_state_res.error == 0):
            return jsonify(success=True)
        else:
            webserver_node.get_logger().error("Vehicle state service call failed")
            return jsonify(success=False, reason="Error")

    except Exception as ex:
        webserver_node.get_logger().error(f"Unable to reach vehicle state server: {ex}")
        return jsonify({"success": False,
                        "reason": "Unable to reach vehicle state server."})
Пример #24
0
def model_file_upload():
    """API to call the service to upload models to the artifacts directory.

    Returns:
        dict: Execution status if the API call was successful and the response message.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    #
    # Check if the file received is a tar.gz
    #
    file_obj = request.files["file"]
    file_name = file_obj.filename
    secured_file = secure_filename(file_name)
    if file_name.endswith(".tar.gz"):
        folder_name = file_name[:-7]
    else:
        return jsonify({
            "success":
            False,
            "message":
            "Failed to upload the model. Not a .tar.gz file"
        })

    # Always create a new directory. If the folder already exists.
    # Delete and Create a new one.
    dir_path = os.path.join(constants.MODEL_DIRECTORY_PATH, folder_name)
    if os.path.exists(dir_path):
        shutil.rmtree(dir_path)
    os.makedirs(dir_path)

    # Save the uploaded file in the artifacts directory.
    webserver_node.get_logger().info(
        "Uploaded model file: {}".format(file_name))
    file_obj.save(os.path.join(dir_path, secured_file))

    # Optimizing the model once the file is uploaded.
    # Converting the .tar.gz to optimized inference model.
    upload_model_req = ConsoleModelActionSrv.Request()
    upload_model_req.model_path = dir_path

    # action=1 (For upload the model) & action=0 for deleting the model
    upload_model_req.action = 1
    upload_model_res = call_service_sync(webserver_node.model_action_cli,
                                         upload_model_req)
    if upload_model_res:
        webserver_node.get_logger().info(
            f"Uploaded model status return {upload_model_res.status}")
        if upload_model_res.status == "done-upload":
            return jsonify({
                "success":
                True,
                "message":
                "Model uploaded successfully to your vehicle"
            })
    return jsonify({
        "success": False,
        "message": "Failed to upload & optimize the model"
    })
Пример #25
0
def load_lidar_configuration(sensors, data):
    """Helper method to load the LiDAR configuration data if present in the model_metadata.json
       file of the data.

    Args:
        sensors (list): List of SensorInputKeys enum objects which the model was trained on.
        data (dict): JSON data with the content read from model_metadata.json of the model.

    Returns:
        tuple: A tuple of error code, error message and the LiDAR configuration dictionary.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    try:
        # Set default values in case the "lidar configuration" is not
        # defined in model_metadata.json.
        model_lidar_config = constants.DEFAULT_LIDAR_CONFIG
        # Set default values for SECTOR_LIDAR if this sensor is used
        if constants.SensorInputKeys.SECTOR_LIDAR in sensors:
            model_lidar_config = constants.DEFAULT_SECTOR_LIDAR_CONFIG
        model_lidar_config[
            constants.ModelMetadataKeys.USE_LIDAR] = sensors and (
                constants.SensorInputKeys.LIDAR in sensors
                or constants.SensorInputKeys.SECTOR_LIDAR in sensors)
        # Load the lidar configuration if the model uses lidar and has custom
        # lidar configurations.
        if model_lidar_config[constants.ModelMetadataKeys.USE_LIDAR] \
           and constants.ModelMetadataKeys.LIDAR_CONFIG in data:
            lidar_config = data[constants.ModelMetadataKeys.LIDAR_CONFIG]
            model_lidar_config[
                constants.ModelMetadataKeys.NUM_LIDAR_VALUES] = lidar_config[
                    constants.ModelMetadataKeys.NUM_LIDAR_VALUES]
            model_lidar_config[
                constants.ModelMetadataKeys.MIN_LIDAR_ANGLE] = lidar_config[
                    constants.ModelMetadataKeys.MIN_LIDAR_ANGLE]
            model_lidar_config[
                constants.ModelMetadataKeys.MAX_LIDAR_ANGLE] = lidar_config[
                    constants.ModelMetadataKeys.MAX_LIDAR_ANGLE]
            model_lidar_config[
                constants.ModelMetadataKeys.MIN_LIDAR_DIST] = lidar_config[
                    constants.ModelMetadataKeys.MIN_LIDAR_DIST]
            model_lidar_config[
                constants.ModelMetadataKeys.MAX_LIDAR_DIST] = lidar_config[
                    constants.ModelMetadataKeys.MAX_LIDAR_DIST]
            model_lidar_config[
                constants.ModelMetadataKeys.
                LIDAR_CLIPPING_DIST] = lidar_config[
                    constants.ModelMetadataKeys.LIDAR_CLIPPING_DIST]
            model_lidar_config[
                constants.ModelMetadataKeys.NUM_LIDAR_SECTORS] = lidar_config[
                    constants.ModelMetadataKeys.NUM_LIDAR_SECTORS]
        return 0, "", model_lidar_config
    except Exception as ex:
        webserver_node.get_logger().error(
            "Unable to connect to vehicle with current "
            f"LiDAR configuration: {ex}")
        return 1, "Unable to connect to vehicle with current LiDAR configuration", {}
def call_service_sync(cli, req, timeout=10, sleep_time=0.01):
    """A wrapper function to call the services and wait for the results until timeout.

    Args:
        cli (rclpy.client.Client): Client object using which we call the service.
        req (Request): Service request object.
        timeout (int, optional): Time in seconds to keep checking for service call to
                                 return result before removing the request. Defaults to 60.
        sleep_time (float, optional): Time in seconds to sleep before each check for
                                      returned result from service call. Defaults to 0.01.

    Returns:
        Response: The service response.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    if cli.service_is_ready():
        webserver_node.get_logger().info(
            f"Service call initiated: {cli.srv_name}")
        future = cli.call_async(req)
        sequence = -1
        for seq, req_future in cli._pending_requests.items():
            if req_future == future:
                sequence = seq
                break
        webserver_node.get_logger().info(
            f"New request: {sequence} {cli.srv_name}")
        elapsed_time = 0
        while not future.done():
            if elapsed_time == int(elapsed_time):
                webserver_node.get_logger().info(
                    f"Service call not finished: {sequence} {cli.srv_name}")
            time.sleep(sleep_time)
            elapsed_time += sleep_time
            if elapsed_time >= timeout:
                webserver_node.get_logger().info(
                    "Service call was not completed before timeout: "
                    f"{sequence} {cli.srv_name} {timeout}")
                future.cancel()
                if future.cancelled():
                    webserver_node.get_logger().error(
                        f"Service was cancelled: {sequence} {cli.srv_name}")
                return None
        webserver_node.get_logger().info(
            f"Service call finished: {sequence} {cli.srv_name}")
        if future.exception() is not None:
            webserver_node.get_logger().error(
                f"Error while calling service: {sequence} - "
                f"{cli.srv_name} - {future.exception()}")
        return future.result()
    else:
        webserver_node.get_logger().info(
            f"Service is not ready: {cli.srv_name}")
        return None
Пример #27
0
def ssh_reset():
    """API called to execute commands to reset the ssh password with the new one.

    Returns:
        dict: Execution status if the API call was successful and with error
              reason if failed.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    webserver_node.get_logger().info(
        "User requesting for resetting the ssh credentials")
    try:
        old_ssh_password = request.json["oldPassword"]
        new_ssh_password = request.json["newPassword"]

        # Check if old password is correct
        if not pam.pam().authenticate(DEFAULT_USER, old_ssh_password):
            return jsonify(success=False,
                           reason="The password is incorrect. "
                           "Provide your current password.")

        # Check if the default password is updated
        passwd_status_cmd = f"/usr/bin/passwd --status {DEFAULT_USER}"
        passwd_status_output = utility.execute(passwd_status_cmd,
                                               shlex_split=True)[1]

        # Execute passwd command based on the status of the password obtained above
        if passwd_status_output.split()[1] == "P":
            webserver_node.get_logger().info("Usable Password present")
            if (utility.execute(
                    f"/usr/bin/sudo -u {DEFAULT_USER} /usr/bin/passwd",
                    input_str=(f"{old_ssh_password}"
                               f"\n{new_ssh_password}"
                               f"\n{new_ssh_password}"),
                    shlex_split=True)[1].find("successfully")) == -1:
                return jsonify(success=False,
                               reason="The password update was unsuccessful.")
            else:
                return jsonify(success=True)
        elif passwd_status_output.split()[1] == "NP":
            webserver_node.get_logger().info("No Password present")
            if (utility.execute(
                    f"/usr/bin/passwd {DEFAULT_USER}",
                    input_str=(f"{new_ssh_password}\n"
                               f"{new_ssh_password}"),
                    shlex_split=True)[1].find("successfully")) > -1:
                return jsonify(success=True)
        else:
            return jsonify(success=False,
                           reason="Unable to change the SSH password")
    except Exception:
        return jsonify(success=False, reason="Error")
Пример #28
0
def is_model_loading():
    """API to stream the model loading status.

    Returns:
        flask.Response: Flask response object with the content_type set to text/event-stream.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()
    is_model_loading_req = GetModelLoadingStatusSrv.Request()
    is_model_loading_res = call_service_sync(
        webserver_node.is_model_loading_cli, is_model_loading_req)
    model_loading_status = "error"
    if is_model_loading_res is not None and is_model_loading_res.error == 0:
        model_loading_status = is_model_loading_res.model_loading_status
    return jsonify({"success": True, "isModelLoading": model_loading_status})
def reset_default():
    """Helper method to reset the password to the default password found on vehicle.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()

    if os.path.exists(DEFAULT_PASSWORD_PATH):
        webserver_node.get_logger().info("Default password file found")
        with open(DEFAULT_PASSWORD_PATH, "r") as pwd_file:
            default_pass = pwd_file.readline().strip()
    else:
        default_pass = "******"
        webserver_node.get_logger().info("Default password file not found")
    with open(DESTINATION_PATH, "w") as pwd_file:
        pwd_file.write(compute_password_digest(default_pass))
    webserver_node.get_logger().info("Password reset to default")
def home_page():
    """API to load home page when if authenticated else redirect to login page.

    Returns:
        flask.Response: Response object with login page or home page details.
    """
    webserver_node = webserver_publisher_node.get_webserver_node()

    status, _ = check_authentication()
    if status:
        webserver_node.get_logger().info("Authenticated")
        return render_template("index.html")
    else:
        resp = make_response(render_template("login.html"), 200)
        return resp