示例#1
0
def saveNozzle():

    if not printer.is_operational():
        return make_response("Printer is not operational", 409)

    valid_commands = {"nozzle": ["nozzleType"]}
    command, data, response = get_json_command_from_request(
        request, valid_commands)
    if response is not None:
        return response

    nozzle = data['nozzleType']

    if not printer.isValidNozzleSize(nozzle):
        return make_response("Invalid nozzle size", 409)

    # converts the nozzle to integer
    nozzle = int(nozzle * 1000)
    resp = printer.setNozzleSize(nozzle)

    printer_profile = printerProfileManager.get_current()
    if printer_profile is not None:
        printer_profile['extruder']['nozzleDiameter'] = nozzle
        printerProfileManager.save(printer_profile, allow_overwrite=True)
    else:
        return jsonify(
            {"response": "Could not find printer profile for saving."})

    return jsonify({"response": resp})
示例#2
0
def pluginCommand(name):
	api_plugins = octoprint.plugin.plugin_manager().get_filtered_implementations(lambda p: p._identifier == name, octoprint.plugin.SimpleApiPlugin)

	if not api_plugins:
		return make_response("Not found", 404)

	if len(api_plugins) > 1:
		return make_response("More than one api provider registered for {name}, can't proceed".format(name=name), 500)

	api_plugin = api_plugins[0]
	valid_commands = api_plugin.get_api_commands()
	if valid_commands is None:
		return make_response("Method not allowed", 405)

	if api_plugin.is_api_adminonly() and not current_user.is_admin():
		return make_response("Forbidden", 403)

	command, data, response = get_json_command_from_request(request, valid_commands)
	if response is not None:
		return response

	response = api_plugin.on_api_command(command, data)
	if response is not None:
		return response
	return NO_CONTENT
示例#3
0
def pluginCommand(name):
	api_plugins = octoprint.plugin.plugin_manager().get_filtered_implementations(lambda p: p._identifier == name, octoprint.plugin.SimpleApiPlugin)

	if not api_plugins:
		return make_response("Not found", 404)

	if len(api_plugins) > 1:
		return make_response("More than one api provider registered for {name}, can't proceed".format(name=name), 500)

	api_plugin = api_plugins[0]
	valid_commands = api_plugin.get_api_commands()
	if valid_commands is None:
		return make_response("Method not allowed", 405)

	if api_plugin.is_api_adminonly() and not current_user.is_admin():
		return make_response("Forbidden", 403)

	command, data, response = get_json_command_from_request(request, valid_commands)
	if response is not None:
		return response

	response = api_plugin.on_api_command(command, data)
	if response is not None:
		return response
	return NO_CONTENT
示例#4
0
def controlJob():
	if not printer.is_operational():
		return make_response("Printer is not operational", 409)

	valid_commands = {
		"start": [],
		"restart": [],
		"pause": [],
		"cancel": []
	}

	command, data, response = get_json_command_from_request(request, valid_commands)
	if response is not None:
		return response

	activePrintjob = printer.is_printing() or printer.is_paused()

	if command == "start":
		if activePrintjob:
			return make_response("Printer already has an active print job, did you mean 'restart'?", 409)
		printer.start_print()
	elif command == "restart":
		if not printer.is_paused():
			return make_response("Printer does not have an active print job or is not paused", 409)
		printer.start_print()
	elif command == "pause":
		if not activePrintjob:
			return make_response("Printer is neither printing nor paused, 'pause' command cannot be performed", 409)
		printer.toggle_pause_print()
	elif command == "cancel":
		if not activePrintjob:
			return make_response("Printer is neither printing nor paused, 'cancel' command cannot be performed", 409)
		printer.cancel_print()
	return NO_CONTENT
示例#5
0
    def bulkOperation(self, target):
        if target not in [FileDestinations.LOCAL, FileDestinations.SDCARD]:
            return make_response("Unknown target: %s" % target, 404)

        worker = self._findFreeWorker()
        if worker == -1:
            return make_response("Too many operations", 429)

        # valid file commands, dict mapping command name to mandatory parameters
        valid_commands = {
            "copy": ["sources", "destinations"],
            "move": ["sources", "destinations"],
            "delete": ["sources"]
        }

        command, data, response = get_json_command_from_request(
            request, valid_commands)
        if response is not None:
            return response

        self.workerPool.add_task(self._bulkOperationThread, worker, target,
                                 command, data["sources"],
                                 data.get("destinations", None))

        return make_response("WorkerID: %d" % worker, 202)
示例#6
0
文件: job.py 项目: 10tux/OctoPrint
def controlJob():
	if not printer.is_operational():
		return make_response("Printer is not operational", 409)

	valid_commands = {
		"start": [],
		"restart": [],
		"pause": [],
		"cancel": []
	}

	command, data, response = get_json_command_from_request(request, valid_commands)
	if response is not None:
		return response

	activePrintjob = printer.is_printing() or printer.is_paused()

	if command == "start":
		if activePrintjob:
			return make_response("Printer already has an active print job, did you mean 'restart'?", 409)
		printer.start_print()
	elif command == "restart":
		if not printer.is_paused():
			return make_response("Printer does not have an active print job or is not paused", 409)
		printer.start_print()
	elif command == "pause":
		if not activePrintjob:
			return make_response("Printer is neither printing nor paused, 'pause' command cannot be performed", 409)
		printer.toggle_pause_print()
	elif command == "cancel":
		if not activePrintjob:
			return make_response("Printer is neither printing nor paused, 'cancel' command cannot be performed", 409)
		printer.cancel_print()
	return NO_CONTENT
示例#7
0
def printerSdCommand():
	if not settings().getBoolean(["feature", "sdSupport"]):
		return make_response("SD support is disabled", 404)

	if not printer.is_operational() or printer.is_printing() or printer.is_paused():
		return make_response("Printer is not operational or currently busy", 409)

	valid_commands = {
		"init": [],
		"refresh": [],
		"release": []
	}
	command, data, response = get_json_command_from_request(request, valid_commands)
	if response is not None:
		return response

	tags = {"source:api", "api:printer.sd"}

	if command == "init":
		printer.init_sd_card(tags=tags)
	elif command == "refresh":
		printer.refresh_sd_files(tags=tags)
	elif command == "release":
		printer.release_sd_card(tags=tags)

	return NO_CONTENT
示例#8
0
def controlJob():
    if not printer.is_operational():
        abort(409, description="Printer is not operational")

    valid_commands = {"start": [], "restart": [], "pause": [], "cancel": []}

    command, data, response = get_json_command_from_request(
        request, valid_commands)
    if response is not None:
        return response

    activePrintjob = printer.is_printing() or printer.is_paused()

    tags = {"source:api", "api:job"}

    user = current_user.get_name()

    with Permissions.PRINT.require(403):
        if command == "start":
            if activePrintjob:
                abort(
                    409,
                    description=
                    "Printer already has an active print job, did you mean 'restart'?",
                )
            printer.start_print(tags=tags, user=user)
        elif command == "restart":
            if not printer.is_paused():
                abort(
                    409,
                    description=
                    "Printer does not have an active print job or is not paused",
                )
            printer.start_print(tags=tags, user=user)
        elif command == "pause":
            if not activePrintjob:
                abort(
                    409,
                    description=
                    "Printer is neither printing nor paused, 'pause' command cannot be performed",
                )
            action = data.get("action", "toggle")
            if action == "toggle":
                printer.toggle_pause_print(tags=tags, user=user)
            elif action == "pause":
                printer.pause_print(tags=tags, user=user)
            elif action == "resume":
                printer.resume_print(tags=tags, user=user)
            else:
                abort(400, description="Unknown action")
        elif command == "cancel":
            if not activePrintjob:
                abort(
                    409,
                    description=
                    "Printer is neither printing nor paused, 'cancel' command cannot be performed",
                )
            printer.cancel_print(tags=tags, user=user)
    return NO_CONTENT
示例#9
0
def printerPrintheadCommand():
    valid_commands = {"jog": [], "home": ["axes"], "feedrate": ["factor"]}
    command, data, response = get_json_command_from_request(
        request, valid_commands)
    if response is not None:
        return response

    if not printer.is_operational() or (printer.is_printing()
                                        and command != "feedrate"):
        # do not jog when a print job is running or we don't have a connection
        return make_response(
            "Printer is not operational or currently printing", 409)

    valid_axes = ["x", "y", "z"]
    ##~~ jog command
    if command == "jog":
        # validate all jog instructions, make sure that the values are numbers
        validated_values = {}
        for axis in valid_axes:
            if axis in data:
                value = data[axis]
                if not isinstance(value, (int, float)):
                    return make_response(
                        "Not a number for axis %s: %r" % (axis, value), 400)
                validated_values[axis] = value

        absolute = "absolute" in data and data[
            "absolute"] in valid_boolean_trues
        speed = data.get("speed", None)

        # execute the jog commands
        printer.jog(validated_values, relative=not absolute, speed=speed)

    ##~~ home command
    elif command == "home":
        validated_values = []
        axes = data["axes"]
        for axis in axes:
            if not axis in valid_axes:
                return make_response("Invalid axis: %s" % axis, 400)
            validated_values.append(axis)

        # execute the home command
        printer.home(validated_values)

    elif command == "feedrate":
        factor = data["factor"]
        if not isinstance(factor, (int, float)):
            return make_response("Not a number for feed rate: %r" % factor,
                                 400)
        try:
            printer.feed_rate(factor)
        except ValueError as e:
            return make_response("Invalid value for feed rate: %s" % str(e),
                                 400)

    return NO_CONTENT
示例#10
0
def printerPrintheadCommand():
	valid_commands = {
		"jog": [],
		"home": ["axes"],
		"feedrate": ["factor"]
	}
	command, data, response = get_json_command_from_request(request, valid_commands)
	if response is not None:
		return response

	if not printer.is_operational() or (printer.is_printing() and command != "feedrate"):
		# do not jog when a print job is running or we don't have a connection
		return make_response("Printer is not operational or currently printing", 409)

	tags = {"source:api", "api:printer.printhead"}

	valid_axes = ["x", "y", "z"]
	##~~ jog command
	if command == "jog":
		# validate all jog instructions, make sure that the values are numbers
		validated_values = {}
		for axis in valid_axes:
			if axis in data:
				value = data[axis]
				if not isinstance(value, (int, long, float)):
					return make_response("Not a number for axis %s: %r" % (axis, value), 400)
				validated_values[axis] = value

		absolute = "absolute" in data and data["absolute"] in valid_boolean_trues
		speed = data.get("speed", None)

		# execute the jog commands
		printer.jog(validated_values, relative=not absolute, speed=speed, tags=tags)

	##~~ home command
	elif command == "home":
		validated_values = []
		axes = data["axes"]
		for axis in axes:
			if not axis in valid_axes:
				return make_response("Invalid axis: %s" % axis, 400)
			validated_values.append(axis)

		# execute the home command
		printer.home(validated_values, tags=tags)

	elif command == "feedrate":
		factor = data["factor"]
		if not isinstance(factor, (int, long, float)):
			return make_response("Not a number for feed rate: %r" % factor, 400)
		try:
			printer.feed_rate(factor, tags=tags)
		except ValueError as e:
			return make_response("Invalid value for feed rate: %s" % str(e), 400)

	return NO_CONTENT
示例#11
0
def controlJob():
    if not printer.is_operational():
        return make_response("Printer is not operational", 409)

    valid_commands = {"start": [], "restart": [], "pause": [], "cancel": []}

    command, data, response = get_json_command_from_request(
        request, valid_commands)
    if response is not None:
        return response

    activePrintjob = printer.is_printing() or printer.is_paused()

    tags = {"source:api", "api:job"}

    user = current_user.get_name()

    with Permissions.PRINT.require(403):
        if command == "start":
            if activePrintjob:
                return make_response(
                    "Printer already has an active print job, did you mean 'restart'?",
                    409)
            printer.start_print(tags=tags, user=user)
        elif command == "restart":
            if not printer.is_paused():
                return make_response(
                    "Printer does not have an active print job or is not paused",
                    409)
            printer.start_print(tags=tags, user=user)
        elif command == "pause":
            if not activePrintjob:
                return make_response(
                    "Printer is neither printing nor paused, 'pause' command cannot be performed",
                    409)
            action = data.get("action", "toggle")
            if action == "toggle":
                printer.toggle_pause_print(tags=tags, user=user)
            elif action == "pause":
                printer.pause_print(tags=tags, user=user)
            elif action == "resume":
                printer.resume_print(tags=tags, user=user)
            else:
                return make_response(
                    "Unknown action '{}', allowed values for action parameter are 'pause', 'resume' and 'toggle'"
                    .format(action), 400)

    # Safety first, everyone can cancel a print, but log who canceled the print
    # to prevent fraudulent use
    if command == "cancel":
        if not activePrintjob:
            return make_response(
                "Printer is neither printing nor paused, 'cancel' command cannot be performed",
                409)
        printer.cancel_print(tags=tags, user=user)
    return NO_CONTENT
示例#12
0
def printerPrintheadCommand():
    valid_commands = {"jog": [], "home": ["axes"], "feedrate": ["factor"]}
    command, data, response = get_json_command_from_request(request, valid_commands)
    if response is not None:
        return response

    if not printer.is_operational() or (printer.is_printing() and command != "feedrate"):
        # do not jog when a print job is running or we don't have a connection
        abort(409, description="Printer is not operational or currently printing")

    tags = {"source:api", "api:printer.printhead"}

    valid_axes = ["x", "y", "z"]
    ##~~ jog command
    if command == "jog":
        # validate all jog instructions, make sure that the values are numbers
        validated_values = {}
        for axis in valid_axes:
            if axis in data:
                value = data[axis]
                if not isinstance(value, (int, long, float)):
                    abort(400, description="axis value is invalid")
                validated_values[axis] = value

        absolute = "absolute" in data and data["absolute"] in valid_boolean_trues
        speed = data.get("speed", None)

        # execute the jog commands
        printer.jog(validated_values, relative=not absolute, speed=speed, tags=tags)

    ##~~ home command
    elif command == "home":
        validated_values = []
        axes = data["axes"]
        for axis in axes:
            if axis not in valid_axes:
                abort(400, description="axis is invalid")
            validated_values.append(axis)

        # execute the home command
        printer.home(validated_values, tags=tags)

    elif command == "feedrate":
        factor = data["factor"]
        if not isinstance(factor, (int, long, float)):
            abort(400, description="factor is invalid")
        try:
            printer.feed_rate(factor, tags=tags)
        except ValueError:
            abort(400, description="factor is invalid")

    return NO_CONTENT
示例#13
0
def utilTest():
    valid_commands = dict(path=["path"], url=["url"], server=["host", "port"])

    command, data, response = get_json_command_from_request(
        request, valid_commands)
    if response is not None:
        return response

    if command == "path":
        return _test_path(data)
    elif command == "url":
        return _test_url(data)
    elif command == "server":
        return _test_server(data)
示例#14
0
def controlJob():
	if not printer.is_operational():
		return make_response("Printer is not operational", 409)

	valid_commands = {
		"start": [],
		"restart": [],
		"pause": [],
		"cancel": [],
		"shutdown": []
	}

	command, data, response = get_json_command_from_request(request, valid_commands)
	if response is not None:
		return response

	activePrintjob = printer.is_printing() or printer.is_paused() or printer.is_preparing_print() or printer.is_shutdown()

	if command == "start":
		if activePrintjob:
			return make_response("Printer already has an active print job, did you mean 'restart'?", 409)
		printer.start_print()
	elif command == "restart":
		if not printer.is_paused():
			return make_response("Printer does not have an active print job or is not paused", 409)
		printer.start_print()
	elif command == "pause":
		if not activePrintjob:
			return make_response("Printer is neither printing nor paused, 'pause' command cannot be performed", 409)
		action = data.get("action", "toggle")
		if action == "toggle":
			printer.toggle_pause_print()
		elif action == "pause":
			printer.pause_print()
		elif action == "resume":
			printer.resume_print()
		else:
			return make_response("Unknown action '{}', allowed values for action parameter are 'pause', 'resume' and 'toggle'".format(action), 400)
	elif command == "cancel":
		if not activePrintjob:
			printer.unselect_file()
		else:
			printer.cancel_print()
	elif command == "shutdown":
		if not printer.is_paused():
			return make_response("Printer does not have an active print job or is not paused", 409)
		printer.enter_shutdown_mode()

	return NO_CONTENT
示例#15
0
def controlJob():
    if not printer.is_operational():
        return make_response("Printer is not operational", 409)

    valid_commands = {"start": [], "restart": [], "pause": [], "cancel": []}

    command, data, response = get_json_command_from_request(
        request, valid_commands)
    if response is not None:
        return response

    activePrintjob = printer.is_printing() or printer.is_paused()

    if command == "start":
        if activePrintjob:
            return make_response(
                "Printer already has an active print job, did you mean 'restart'?",
                409)
        printer.start_print()
    elif command == "restart":
        if not printer.is_paused():
            return make_response(
                "Printer does not have an active print job or is not paused",
                409)
        printer.start_print()
    elif command == "pause":
        if not activePrintjob:
            return make_response(
                "Printer is neither printing nor paused, 'pause' command cannot be performed",
                409)
        action = data.get("action", "toggle")
        if action == "toggle":
            printer.toggle_pause_print()
        elif action == "pause":
            printer.pause_print()
        elif action == "resume":
            printer.resume_print()
        else:
            return make_response(
                "Unknown action '{}', allowed values for action parameter are 'pause', 'resume' and 'toggle'"
                .format(action), 400)
    elif command == "cancel":
        if not activePrintjob:
            return make_response(
                "Printer is neither printing nor paused, 'cancel' command cannot be performed",
                409)
        printer.cancel_print()
    return NO_CONTENT
示例#16
0
def processUnrenderedTimelapseCommand(name):
    # valid file commands, dict mapping command name to mandatory parameters
    valid_commands = {"render": []}

    command, data, response = get_json_command_from_request(
        request, valid_commands)
    if response is not None:
        return response

    if command == "render":
        if printer.is_printing() or printer.is_paused():
            return make_response(
                "Printer is currently printing, cannot render timelapse", 409)
        octoprint.timelapse.render_unrendered_timelapse(name)

    return NO_CONTENT
示例#17
0
def processUnrenderedTimelapseCommand(name):
	# valid file commands, dict mapping command name to mandatory parameters
	valid_commands = {
		"render": []
	}

	command, data, response = get_json_command_from_request(request, valid_commands)
	if response is not None:
		return response

	if command == "render":
		if printer.is_printing() or printer.is_paused():
			return make_response("Printer is currently printing, cannot render timelapse", 409)
		octoprint.timelapse.render_unrendered_timelapse(name)

	return NO_CONTENT
示例#18
0
def saveFilament():

    if not printer.is_operational():
        return make_response("Printer is not operational", 409)

    valid_commands = {"filament": ["filamentStr"]}
    command, data, response = get_json_command_from_request(
        request, valid_commands)
    if response is not None:
        return response

    filamentStr = data['filamentStr']

    resp = printer.setFilamentString(filamentStr)

    return jsonify({"response": resp})
示例#19
0
def utilTest():
	valid_commands = dict(
		path=["path"],
		url=["url"],
		server=["host", "port"]
	)

	command, data, response = get_json_command_from_request(request, valid_commands)
	if response is not None:
		return response

	if command == "path":
		return _test_path(data)
	elif command == "url":
		return _test_url(data)
	elif command == "server":
		return _test_server(data)
示例#20
0
def connectionCommand():
    valid_commands = {"connect": [], "disconnect": []}

    command, data, response = get_json_command_from_request(
        request, valid_commands)
    if response is not None:
        return response

    if command == "connect":
        connection_options = get_connection_options()

        port = None
        port1 = None
        projector = None
        baudrate = None
        printerProfile = None
        if "port" in data.keys():
            port = data["port"]
            if port not in connection_options["ports"]:
                return make_response("Invalid port: %s" % port, 400)
        if "baudrate" in data.keys():
            baudrate = data["baudrate"]
            if baudrate not in connection_options["baudrates"]:
                return make_response("Invalid baudrate: %d" % baudrate, 400)
        if "printerProfile" in data.keys():
            printerProfile = data["printerProfile"]
            if not printerProfileManager.exists(printerProfile):
                return make_response(
                    "Invalid printer profile: %s" % printerProfile, 400)
        if "save" in data.keys() and data["save"]:
            port1 = data["port1"]
            projector = data["projector"]
            settings().set(["serial", "port"], port)
            settings().set(["serial", "port1"], port1)
            settings().set(["serial", "projector"], projector)
            settings().setInt(["serial", "baudrate"], baudrate)
            printerProfileManager.set_default(printerProfile)
        if "autoconnect" in data.keys():
            settings().setBoolean(["serial", "autoconnect"],
                                  data["autoconnect"])
        settings().save()
        printer.connect(port=port, baudrate=baudrate, profile=printerProfile)
    elif command == "disconnect":
        printer.disconnect()

    return NO_CONTENT
示例#21
0
def runFilesTest():
    valid_commands = {
        "sanitize": ["storage", "path", "filename"],
        "exists": ["storage", "path", "filename"],
    }

    command, data, response = get_json_command_from_request(
        request, valid_commands)
    if response is not None:
        return response

    def sanitize(storage, path, filename):
        sanitized_path = fileManager.sanitize_path(storage, path)
        sanitized_name = fileManager.sanitize_name(storage, filename)
        joined = fileManager.join_path(storage, sanitized_path, sanitized_name)
        return sanitized_path, sanitized_name, joined

    if command == "sanitize":
        _, _, sanitized = sanitize(data["storage"], data["path"],
                                   data["filename"])
        return jsonify(sanitized=sanitized)
    elif command == "exists":
        storage = data["storage"]
        path = data["path"]
        filename = data["filename"]

        sanitized_path, _, sanitized = sanitize(storage, path, filename)

        exists = fileManager.file_exists(storage, sanitized)
        if exists:
            suggestion = filename
            name, ext = os.path.splitext(filename)
            counter = 0
            while fileManager.file_exists(
                    storage,
                    fileManager.join_path(
                        storage,
                        sanitized_path,
                        fileManager.sanitize_name(storage, suggestion),
                    ),
            ):
                counter += 1
                suggestion = name + "_{}".format(counter) + ext
            return jsonify(exists=True, suggestion=suggestion)
        else:
            return jsonify(exists=False)
示例#22
0
def setFilamentWeight():

    if not printer.is_operational():
        return make_response("Printer is not operational", 409)

    valid_commands = {"filament": ["filamentWeight"]}
    command, data, response = get_json_command_from_request(
        request, valid_commands)
    if response is not None:
        return response

    filamentWeight = data['filamentWeight']

    resp = "Invalid filament weight"

    if filamentWeight and float(filamentWeight) >= 0:
        resp = printer.setFilamentInSpool(float(filamentWeight))

    return jsonify({"response": resp})
示例#23
0
def connectionCommand():
	valid_commands = {
		"connect": [],
		"disconnect": [],
		"fake_ack": []
	}

	command, data, response = get_json_command_from_request(request, valid_commands)
	if response is not None:
		return response

	if command == "connect":
		connection_options = get_connection_options()

		port = None
		baudrate = None
		printerProfile = None
		if "port" in data.keys():
			port = data["port"]
			if port not in connection_options["ports"] and port != "AUTO":
				return make_response("Invalid port: %s" % port, 400)
		if "baudrate" in data.keys():
			baudrate = data["baudrate"]
			if baudrate not in connection_options["baudrates"] and baudrate != 0:
				return make_response("Invalid baudrate: %d" % baudrate, 400)
		if "printerProfile" in data.keys():
			printerProfile = data["printerProfile"]
			if not printerProfileManager.exists(printerProfile):
				return make_response("Invalid printer profile: %s" % printerProfile, 400)
		if "save" in data.keys() and data["save"]:
			settings().set(["serial", "port"], port)
			settings().setInt(["serial", "baudrate"], baudrate)
			printerProfileManager.set_default(printerProfile)
		if "autoconnect" in data.keys():
			settings().setBoolean(["serial", "autoconnect"], data["autoconnect"])
		settings().save()
		printer.connect(port=port, baudrate=baudrate, profile=printerProfile)
	elif command == "disconnect":
		printer.disconnect()
	elif command == "fake_ack":
		printer.fake_ack()

	return NO_CONTENT
示例#24
0
	def channel_command(self, channel):
		from octoprint.server.util.flask import get_json_command_from_request
		from octoprint.server import NO_CONTENT

		valid_commands = dict(read=["until"],
		                      toggle=[])

		command, data, response = get_json_command_from_request(flask.request, valid_commands=valid_commands)
		if response is not None:
			return response

		if command == "read":
			until = data["until"]
			self._mark_read_until(channel, until)

		elif command == "toggle":
			self._toggle(channel)

		return NO_CONTENT
示例#25
0
    def channel_command(self, channel):
        from octoprint.server.util.flask import get_json_command_from_request
        from octoprint.server import NO_CONTENT

        valid_commands = dict(read=["until"], toggle=[])

        command, data, response = get_json_command_from_request(
            flask.request, valid_commands=valid_commands)
        if response is not None:
            return response

        if command == "read":
            until = data["until"]
            self._mark_read_until(channel, until)

        elif command == "toggle":
            self._toggle(channel)

        return NO_CONTENT
示例#26
0
    def handle_decision(self):
        valid_commands = {"decision": []}

        command, data, response = get_json_command_from_request(
            flask.request, valid_commands)
        if response is not None:
            return response

        client_key = data.get("clientKey", "")
        if not client_key:
            return NO_CONTENT

        self._plugin_manager.send_plugin_message(
            self._identifier, dict(type="end_request", clientKey=client_key))

        self._decisions[client_key] = (data.get("accessGranted", False),
                                       data.get("userName", ""))

        return NO_CONTENT
示例#27
0
def printerChamberCommand():
	if not printer.is_operational():
		return make_response("Printer is not operational", 409)

	if not printerProfileManager.get_current_or_default()["heatedChamber"]:
		return make_response("Printer does not have a heated chamber", 409)

	valid_commands = {
		"target": ["target"],
		"offset": ["offset"]
	}
	command, data, response = get_json_command_from_request(request, valid_commands)
	if response is not None:
		return response

	tags = {"source:api", "api:printer.chamber"}

	##~~ temperature
	if command == "target":
		target = data["target"]

		# make sure the target is a number
		if not isinstance(target, (int, long, float)):
			return make_response("Not a number: %r" % target, 400)

		# perform the actual temperature command
		printer.set_temperature("chamber", target, tags=tags)

	##~~ temperature offset
	elif command == "offset":
		offset = data["offset"]

		# make sure the offset is valid
		if not isinstance(offset, (int, long, float)):
			return make_response("Not a number: %r" % offset, 400)
		if not -50 <= offset <= 50:
			return make_response("Offset not in range [-50, 50]: %f" % offset, 400)

		# set the offsets
		printer.set_temperature_offset({"chamber": offset})

	return NO_CONTENT
示例#28
0
def connectionCommand():
    valid_commands = {"connect": [], "disconnect": [], "fake_ack": []}

    command, data, response = get_json_command_from_request(
        request, valid_commands)
    if response is not None:
        return response

    if command == "connect":
        connection_options = printer.__class__.get_connection_options()

        port = None
        baudrate = None
        printerProfile = None
        if "port" in data:
            port = data["port"]
            if port not in connection_options["ports"] and port != "AUTO":
                abort(400, description="port is invalid")
        if "baudrate" in data:
            baudrate = data["baudrate"]
            if baudrate not in connection_options[
                    "baudrates"] and baudrate != 0:
                abort(400, description="baudrate is invalid")
        if "printerProfile" in data:
            printerProfile = data["printerProfile"]
            if not printerProfileManager.exists(printerProfile):
                abort(400, description="printerProfile is invalid")
        if "save" in data and data["save"]:
            settings().set(["serial", "port"], port)
            settings().setInt(["serial", "baudrate"], baudrate)
            printerProfileManager.set_default(printerProfile)
        if "autoconnect" in data:
            settings().setBoolean(["serial", "autoconnect"],
                                  data["autoconnect"])
        settings().save()
        printer.connect(port=port, baudrate=baudrate, profile=printerProfile)
    elif command == "disconnect":
        printer.disconnect()
    elif command == "fake_ack":
        printer.fake_ack()

    return NO_CONTENT
示例#29
0
def pluginCommand(name):
    api_plugins = octoprint.plugin.plugin_manager(
    ).get_filtered_implementations(lambda p: p._identifier == name,
                                   octoprint.plugin.SimpleApiPlugin)

    if not api_plugins:
        return make_response("Not found", 404)

    if len(api_plugins) > 1:
        return make_response(
            "More than one api provider registered for {name}, can't proceed".
            format(name=name),
            500,
        )

    api_plugin = api_plugins[0]
    try:
        valid_commands = api_plugin.get_api_commands()
        if valid_commands is None:
            return make_response("Method not allowed", 405)

        if api_plugin.is_api_adminonly() and not Permissions.ADMIN.can():
            return make_response("Forbidden", 403)

        command, data, response = get_json_command_from_request(
            request, valid_commands)
        if response is not None:
            return response

        response = api_plugin.on_api_command(command, data)
        if response is not None:
            return response
        return NO_CONTENT
    except HTTPException:
        raise
    except Exception:
        logging.getLogger(__name__).exception(
            "Error while executing SimpleApiPlugin {}".format(name),
            extra={"plugin": name},
        )
        return abort(500)
示例#30
0
    def channel_command(self, channel):
        from octoprint.server import NO_CONTENT
        from octoprint.server.util.flask import get_json_command_from_request

        valid_commands = {"read": ["until"], "toggle": []}

        command, data, response = get_json_command_from_request(
            flask.request, valid_commands=valid_commands)
        if response is not None:
            return response

        if command == "read":
            until = data["until"]
            self._mark_read_until(channel, until)

        elif command == "toggle":
            if not Permissions.PLUGIN_ANNOUNCEMENTS_MANAGE.can():
                flask.abort(403)
            self._toggle(channel)

        return NO_CONTENT
示例#31
0
	def channel_command(self, channel):
		from octoprint.server.util.flask import get_json_command_from_request
		from octoprint.server import NO_CONTENT

		valid_commands = dict(read=["until"],
		                      toggle=[])

		command, data, response = get_json_command_from_request(flask.request, valid_commands=valid_commands)
		if response is not None:
			return response

		if command == "read":
			until = data["until"]
			self._mark_read_until(channel, until)

		elif command == "toggle":
			if not Permissions.PLUGIN_ANNOUNCEMENTS_MANAGE.can():
				return flask.make_response("Insufficient rights", 403)
			self._toggle(channel)

		return NO_CONTENT
示例#32
0
	def bulkOperation(self, target):
		if target not in [FileDestinations.LOCAL, FileDestinations.SDCARD]:
			return make_response("Unknown target: %s" % target, 404)

		worker = self._findFreeWorker()
		if worker == -1:
			return make_response("Too many operations", 429)

		# valid file commands, dict mapping command name to mandatory parameters
		valid_commands = {
			"copy": ["sources", "destinations"],
			"move": ["sources", "destinations"],
			"delete": ["sources"]
		}

		command, data, response = get_json_command_from_request(request, valid_commands)
		if response is not None:
			return response

		self.workerPool.add_task(self._bulkOperationThread, worker, target, command, data["sources"], data.get("destinations", None))

		return make_response("WorkerID: %d" % worker, 202)
示例#33
0
def printerBedCommand():
    if not printer.is_operational():
        abort(409, description="Printer is not operational")

    if not printerProfileManager.get_current_or_default()["heatedBed"]:
        abort(409, description="Printer does not have a heated bed")

    valid_commands = {"target": ["target"], "offset": ["offset"]}
    command, data, response = get_json_command_from_request(request, valid_commands)
    if response is not None:
        return response

    tags = {"source:api", "api:printer.bed"}

    ##~~ temperature
    if command == "target":
        target = data["target"]

        # make sure the target is a number
        if not isinstance(target, (int, long, float)):
            abort(400, description="target is invalid")

        # perform the actual temperature command
        printer.set_temperature("bed", target, tags=tags)

    ##~~ temperature offset
    elif command == "offset":
        offset = data["offset"]

        # make sure the offset is valid
        if not isinstance(offset, (int, long, float)) or not -50 <= offset <= 50:
            abort(400, description="offset is invalid")

        # set the offsets
        printer.set_temperature_offset({"bed": offset})

    return NO_CONTENT
示例#34
0
def printerBedCommand():
	if not printer.is_operational():
		return make_response("Printer is not operational", 409)

	valid_commands = {
		"target": ["target"],
		"offset": ["offset"]
	}
	command, data, response = get_json_command_from_request(request, valid_commands)
	if response is not None:
		return response

	##~~ temperature
	if command == "target":
		target = data["target"]

		# make sure the target is a number
		if not isinstance(target, (int, long, float)):
			return make_response("Not a number: %r" % target, 400)

		# perform the actual temperature command
		printer.set_temperature("bed", target)

	##~~ temperature offset
	elif command == "offset":
		offset = data["offset"]

		# make sure the offset is valid
		if not isinstance(offset, (int, long, float)):
			return make_response("Not a number: %r" % offset, 400)
		if not -50 <= offset <= 50:
			return make_response("Offset not in range [-50, 50]: %f" % offset, 400)

		# set the offsets
		printer.set_temperature_offset({"bed": offset})

	return NO_CONTENT
示例#35
0
def printersetCommand():
	valid_commands = {
		"save": [],
	}

	command, data, response = get_json_command_from_request(request, valid_commands)
	if response is not None:
		return response

	if command == "save":
		settings().set(["printerset", "blayer"],data["blayer"])
		settings().set(["printerset", "xpx"],data["xpx"])
		settings().set(["printerset", "layert"],data["layert"])
		settings().set(["printerset", "ypx"],data["ypx"])
		settings().set(["printerset", "prox"],data["prox"])
		settings().set(["printerset", "offx"],data["offx"])
		settings().set(["printerset", "offy"],data["offy"])
		settings().set(["printerset", "nres"],data["nres"])
		settings().set(["printerset", "spec"],data["spec"])
		settings().set(["printerset", "shutter"],data["shutter"])
		settings().set(["printerset", "mask"],data["mask"])
		settings().set(["printerset", "printmode"],data["printmode"])
		settings().save()
	return NO_CONTENT
示例#36
0
def utilTest():
    valid_commands = {
        "path": ["path"],
        "url": ["url"],
        "server": ["host", "port"],
        "resolution": ["name"],
        "address": [],
    }

    command, data, response = get_json_command_from_request(
        request, valid_commands)
    if response is not None:
        return response

    if command == "path":
        return _test_path(data)
    elif command == "url":
        return _test_url(data)
    elif command == "server":
        return _test_server(data)
    elif command == "resolution":
        return _test_resolution(data)
    elif command == "address":
        return _test_address(data)
示例#37
0
def printersetCommand2():
	valid_commands = {
		"save": [],
	}

	command, data, response = get_json_command_from_request(request, valid_commands)
	if response is not None:
		return response

	if command == "save":
		if printer.piflag == 1:
			upload_dir = "/root/.octoprint/uploads/"	# tempfile.mkdtemp()
		else:
			upload_dir = "/home/maxchen/.octoprint/uploads/"	# tempfile.mkdtemp()
		f = open(upload_dir+data["filename"], 'w')
		# Header information


		f.write(data["content"])
		f.close()
		#added_file = fileManager.add_file(FileDestinations.LOCAL, data["filename"], data["content"], allow_overwrite=True)
		eventManager.fire(Events.UPLOAD, {"file": data["filename"], "target": "local"})
		eventManager.fire(Events.UPDATED_FILES, dict(type="printables"))
	return NO_CONTENT
示例#38
0
文件: files.py 项目: devdej/OctoPrint
def gcodeFileCommand(filename, target):
	if not target in [FileDestinations.LOCAL, FileDestinations.SDCARD]:
		return make_response("Unknown target: %s" % target, 404)

	# valid file commands, dict mapping command name to mandatory parameters
	valid_commands = {
		"select": [],
		"slice": [],
		"copy": ["destination"],
		"move": ["destination"]
	}

	command, data, response = get_json_command_from_request(request, valid_commands)
	if response is not None:
		return response

	if command == "select":
		if not _verifyFileExists(target, filename):
			return make_response("File not found on '%s': %s" % (target, filename), 404)

		# selects/loads a file
		if not octoprint.filemanager.valid_file_type(filename, type="machinecode"):
			return make_response("Cannot select {filename} for printing, not a machinecode file".format(**locals()), 415)

		printAfterLoading = False
		if "print" in data.keys() and data["print"] in valid_boolean_trues:
			if not printer.is_operational():
				return make_response("Printer is not operational, cannot directly start printing", 409)
			printAfterLoading = True

		sd = False
		if target == FileDestinations.SDCARD:
			filenameToSelect = filename
			sd = True
		else:
			filenameToSelect = fileManager.path_on_disk(target, filename)
		printer.select_file(filenameToSelect, sd, printAfterLoading)

	elif command == "slice":
		if not _verifyFileExists(target, filename):
			return make_response("File not found on '%s': %s" % (target, filename), 404)

		try:
			if "slicer" in data:
				slicer = data["slicer"]
				del data["slicer"]
				slicer_instance = slicingManager.get_slicer(slicer)

			elif "cura" in slicingManager.registered_slicers:
				slicer = "cura"
				slicer_instance = slicingManager.get_slicer("cura")

			else:
				return make_response("Cannot slice {filename}, no slicer available".format(**locals()), 415)
		except octoprint.slicing.UnknownSlicer as e:
			return make_response("Slicer {slicer} is not available".format(slicer=e.slicer), 400)

		if not any([octoprint.filemanager.valid_file_type(filename, type=source_file_type) for source_file_type in slicer_instance.get_slicer_properties().get("source_file_types", ["model"])]):
			return make_response("Cannot slice {filename}, not a model file".format(**locals()), 415)

		if slicer_instance.get_slicer_properties().get("same_device", True) and (printer.is_printing() or printer.is_paused()):
			# slicer runs on same device as OctoPrint, slicing while printing is hence disabled
			return make_response("Cannot slice on {slicer} while printing due to performance reasons".format(**locals()), 409)

		if "destination" in data and data["destination"]:
			destination = data["destination"]
			del data["destination"]
		elif "gcode" in data and data["gcode"]:
			destination = data["gcode"]
			del data["gcode"]
		else:
			import os
			name, _ = os.path.splitext(filename)
			destination = name + "." + slicer_instance.get_slicer_properties().get("destination_extensions", ["gco", "gcode", "g"])[0]

		full_path = destination
		if "path" in data and data["path"]:
			full_path = fileManager.join_path(target, data["path"], destination)
		else:
			path, _ = fileManager.split_path(target, filename)
			if path:
				full_path = fileManager.join_path(target, path, destination)

		# prohibit overwriting the file that is currently being printed
		currentOrigin, currentFilename = _getCurrentFile()
		if currentFilename == full_path and currentOrigin == target and (printer.is_printing() or printer.is_paused()):
			make_response("Trying to slice into file that is currently being printed: %s" % full_path, 409)

		if "profile" in data.keys() and data["profile"]:
			profile = data["profile"]
			del data["profile"]
		else:
			profile = None

		if "printerProfile" in data.keys() and data["printerProfile"]:
			printerProfile = data["printerProfile"]
			del data["printerProfile"]
		else:
			printerProfile = None

		if "position" in data.keys() and data["position"] and isinstance(data["position"], dict) and "x" in data["position"] and "y" in data["position"]:
			position = data["position"]
			del data["position"]
		else:
			position = None

		select_after_slicing = False
		if "select" in data.keys() and data["select"] in valid_boolean_trues:
			if not printer.is_operational():
				return make_response("Printer is not operational, cannot directly select for printing", 409)
			select_after_slicing = True

		print_after_slicing = False
		if "print" in data.keys() and data["print"] in valid_boolean_trues:
			if not printer.is_operational():
				return make_response("Printer is not operational, cannot directly start printing", 409)
			select_after_slicing = print_after_slicing = True

		override_keys = [k for k in data if k.startswith("profile.") and data[k] is not None]
		overrides = dict()
		for key in override_keys:
			overrides[key[len("profile."):]] = data[key]

		def slicing_done(target, path, select_after_slicing, print_after_slicing):
			if select_after_slicing or print_after_slicing:
				sd = False
				if target == FileDestinations.SDCARD:
					filenameToSelect = path
					sd = True
				else:
					filenameToSelect = fileManager.path_on_disk(target, path)
				printer.select_file(filenameToSelect, sd, print_after_slicing)

		try:
			fileManager.slice(slicer, target, filename, target, full_path,
			                  profile=profile,
			                  printer_profile_id=printerProfile,
			                  position=position,
			                  overrides=overrides,
			                  callback=slicing_done,
			                  callback_args=(target, full_path, select_after_slicing, print_after_slicing))
		except octoprint.slicing.UnknownProfile:
			return make_response("Profile {profile} doesn't exist".format(**locals()), 400)

		files = {}
		location = url_for(".readGcodeFile", target=target, filename=full_path, _external=True)
		result = {
			"name": destination,
			"path": full_path,
			"origin": FileDestinations.LOCAL,
			"refs": {
				"resource": location,
				"download": url_for("index", _external=True) + "downloads/files/" + target + "/" + full_path
			}
		}

		r = make_response(jsonify(result), 202)
		r.headers["Location"] = location
		return r

	elif command == "copy" or command == "move":
		# Copy and move are only possible on local storage
		if not target in [FileDestinations.LOCAL]:
			return make_response("Unsupported target for {}: {}".format(command, target), 400)

		if not _verifyFileExists(target, filename) and not _verifyFolderExists(target, filename):
			return make_response("File or folder not found on {}: {}".format(target, filename), 404)

		path, name = fileManager.split_path(target, filename)
		destination = data["destination"]
		if _verifyFolderExists(target, destination):
			# destination is an existing folder, we'll assume we are supposed to move filename to this
			# folder under the same name
			destination = fileManager.join_path(target, destination, name)

		if _verifyFileExists(target, destination) or _verifyFolderExists(target, destination):
			return make_response("File or folder does already exist on {}: {}".format(target, destination), 409)

		is_file = fileManager.file_exists(target, filename)
		is_folder = fileManager.folder_exists(target, filename)

		if not (is_file or is_folder):
			return make_response("{} on {} is neither file or folder, can't {}".format(filename, target, command), 400)

		if command == "copy":
			if is_file:
				fileManager.copy_file(target, filename, destination)
			else:
				fileManager.copy_folder(target, filename, destination)
		elif command == "move":
			if _isBusy(target, filename):
				return make_response("Trying to move a file or folder that is currently in use: {}".format(filename), 409)

			# deselect the file if it's currently selected
			currentOrigin, currentFilename = _getCurrentFile()
			if currentFilename is not None and filename == currentFilename:
				printer.unselect_file()

			if is_file:
				fileManager.move_file(target, filename, destination)
			else:
				fileManager.move_folder(target, filename, destination)

		location = url_for(".readGcodeFile", target=target, filename=destination, _external=True)
		result = {
			"name": name,
			"path": destination,
			"origin": FileDestinations.LOCAL,
			"refs": {
				"resource": location
			}
		}
		if is_file:
			result["refs"]["download"] = url_for("index", _external=True) + "downloads/files/" + target + "/" + destination

		r = make_response(jsonify(result), 201)
		r.headers["Location"] = location
		return r

	return NO_CONTENT
示例#39
0
def gcodeFileCommand(filename, target):
	if not target in [FileDestinations.LOCAL, FileDestinations.SDCARD]:
		return make_response("Unknown target: %s" % target, 404)

	# valid file commands, dict mapping command name to mandatory parameters
	valid_commands = {
		"select": [],
		"slice": [],
		"analyse": [],
		"copy": ["destination"],
		"move": ["destination"]
	}

	command, data, response = get_json_command_from_request(request, valid_commands)
	if response is not None:
		return response

	user = current_user.get_name()

	if command == "select":
		if not _verifyFileExists(target, filename):
			return make_response("File not found on '%s': %s" % (target, filename), 404)

		# selects/loads a file
		if not octoprint.filemanager.valid_file_type(filename, type="machinecode"):
			return make_response("Cannot select {filename} for printing, not a machinecode file".format(**locals()), 415)

		printAfterLoading = False
		if "print" in data.keys() and data["print"] in valid_boolean_trues:
			if not printer.is_operational():
				return make_response("Printer is not operational, cannot directly start printing", 409)
			printAfterLoading = True

		sd = False
		if target == FileDestinations.SDCARD:
			filenameToSelect = filename
			sd = True
		else:
			filenameToSelect = fileManager.path_on_disk(target, filename)
		printer.select_file(filenameToSelect, sd, printAfterLoading, user)

	elif command == "slice":
		if not _verifyFileExists(target, filename):
			return make_response("File not found on '%s': %s" % (target, filename), 404)

		try:
			if "slicer" in data:
				slicer = data["slicer"]
				del data["slicer"]
				slicer_instance = slicingManager.get_slicer(slicer)

			elif "cura" in slicingManager.registered_slicers:
				slicer = "cura"
				slicer_instance = slicingManager.get_slicer("cura")

			else:
				return make_response("Cannot slice {filename}, no slicer available".format(**locals()), 415)
		except octoprint.slicing.UnknownSlicer as e:
			return make_response("Slicer {slicer} is not available".format(slicer=e.slicer), 400)

		if not any([octoprint.filemanager.valid_file_type(filename, type=source_file_type) for source_file_type in slicer_instance.get_slicer_properties().get("source_file_types", ["model"])]):
			return make_response("Cannot slice {filename}, not a model file".format(**locals()), 415)

		if slicer_instance.get_slicer_properties().get("same_device", True) and (printer.is_printing() or printer.is_paused()):
			# slicer runs on same device as OctoPrint, slicing while printing is hence disabled
			return make_response("Cannot slice on {slicer} while printing due to performance reasons".format(**locals()), 409)

		if "destination" in data and data["destination"]:
			destination = data["destination"]
			del data["destination"]
		elif "gcode" in data and data["gcode"]:
			destination = data["gcode"]
			del data["gcode"]
		else:
			import os
			name, _ = os.path.splitext(filename)
			destination = name + "." + slicer_instance.get_slicer_properties().get("destination_extensions", ["gco", "gcode", "g"])[0]

		full_path = destination
		if "path" in data and data["path"]:
			full_path = fileManager.join_path(target, data["path"], destination)
		else:
			path, _ = fileManager.split_path(target, filename)
			if path:
				full_path = fileManager.join_path(target, path, destination)

		canon_path, canon_name = fileManager.canonicalize(target, full_path)
		sanitized_name = fileManager.sanitize_name(target, canon_name)

		if canon_path:
			full_path = fileManager.join_path(target, canon_path, sanitized_name)
		else:
			full_path = sanitized_name

		# prohibit overwriting the file that is currently being printed
		currentOrigin, currentFilename = _getCurrentFile()
		if currentFilename == full_path and currentOrigin == target and (printer.is_printing() or printer.is_paused()):
			make_response("Trying to slice into file that is currently being printed: %s" % full_path, 409)

		if "profile" in data.keys() and data["profile"]:
			profile = data["profile"]
			del data["profile"]
		else:
			profile = None

		if "printerProfile" in data.keys() and data["printerProfile"]:
			printerProfile = data["printerProfile"]
			del data["printerProfile"]
		else:
			printerProfile = None

		if "position" in data.keys() and data["position"] and isinstance(data["position"], dict) and "x" in data["position"] and "y" in data["position"]:
			position = data["position"]
			del data["position"]
		else:
			position = None

		select_after_slicing = False
		if "select" in data.keys() and data["select"] in valid_boolean_trues:
			if not printer.is_operational():
				return make_response("Printer is not operational, cannot directly select for printing", 409)
			select_after_slicing = True

		print_after_slicing = False
		if "print" in data.keys() and data["print"] in valid_boolean_trues:
			if not printer.is_operational():
				return make_response("Printer is not operational, cannot directly start printing", 409)
			select_after_slicing = print_after_slicing = True

		override_keys = [k for k in data if k.startswith("profile.") and data[k] is not None]
		overrides = dict()
		for key in override_keys:
			overrides[key[len("profile."):]] = data[key]

		def slicing_done(target, path, select_after_slicing, print_after_slicing):
			if select_after_slicing or print_after_slicing:
				sd = False
				if target == FileDestinations.SDCARD:
					filenameToSelect = path
					sd = True
				else:
					filenameToSelect = fileManager.path_on_disk(target, path)
				printer.select_file(filenameToSelect, sd, print_after_slicing, user)

		try:
			fileManager.slice(slicer, target, filename, target, full_path,
			                  profile=profile,
			                  printer_profile_id=printerProfile,
			                  position=position,
			                  overrides=overrides,
			                  display=canon_name,
			                  callback=slicing_done,
			                  callback_args=(target, full_path, select_after_slicing, print_after_slicing))
		except octoprint.slicing.UnknownProfile:
			return make_response("Profile {profile} doesn't exist".format(**locals()), 400)

		files = {}
		location = url_for(".readGcodeFile", target=target, filename=full_path, _external=True)
		result = {
			"name": sanitized_name,
			"path": full_path,
			"display": canon_name,
			"origin": FileDestinations.LOCAL,
			"refs": {
				"resource": location,
				"download": url_for("index", _external=True) + "downloads/files/" + target + "/" + full_path
			}
		}

		r = make_response(jsonify(result), 202)
		r.headers["Location"] = location
		return r

	elif command == "analyse":
		if not _verifyFileExists(target, filename):
			return make_response("File not found on '%s': %s" % (target, filename), 404)

		printer_profile = None
		if "printerProfile" in data and data["printerProfile"]:
			printer_profile = data["printerProfile"]

		if not fileManager.analyse(target, filename, printer_profile_id=printer_profile):
			return make_response("No analysis possible for {} on {}".format(filename, target), 400)

	elif command == "copy" or command == "move":
		# Copy and move are only possible on local storage
		if not target in [FileDestinations.LOCAL]:
			return make_response("Unsupported target for {}: {}".format(command, target), 400)

		if not _verifyFileExists(target, filename) and not _verifyFolderExists(target, filename):
			return make_response("File or folder not found on {}: {}".format(target, filename), 404)

		path, name = fileManager.split_path(target, filename)

		destination = data["destination"]
		dst_path, dst_name = fileManager.split_path(target, destination)
		sanitized_destination = fileManager.join_path(target, dst_path, fileManager.sanitize_name(target, dst_name))

		if _verifyFolderExists(target, destination) and sanitized_destination != filename:
			# destination is an existing folder and not ourselves (= display rename), we'll assume we are supposed
			# to move filename to this folder under the same name
			destination = fileManager.join_path(target, destination, name)

		is_file = fileManager.file_exists(target, filename)
		is_folder = fileManager.folder_exists(target, filename)

		if not (is_file or is_folder):
			return make_response("{} on {} is neither file or folder, can't {}".format(filename, target, command), 400)

		if command == "copy":
			# destination already there? error...
			if _verifyFileExists(target, destination) or _verifyFolderExists(target, destination):
				return make_response("File or folder does already exist on {}: {}".format(target, destination), 409)

			if is_file:
				fileManager.copy_file(target, filename, destination)
			else:
				fileManager.copy_folder(target, filename, destination)

		elif command == "move":
			if _isBusy(target, filename):
				return make_response("Trying to move a file or folder that is currently in use: {}".format(filename), 409)

			# destination already there AND not ourselves (= display rename)? error...
			if (_verifyFileExists(target, destination) or _verifyFolderExists(target, destination)) \
					and sanitized_destination != filename:
				return make_response("File or folder does already exist on {}: {}".format(target, destination), 409)

			# deselect the file if it's currently selected
			currentOrigin, currentFilename = _getCurrentFile()
			if currentFilename is not None and filename == currentFilename:
				printer.unselect_file()

			if is_file:
				fileManager.move_file(target, filename, destination)
			else:
				fileManager.move_folder(target, filename, destination)

		location = url_for(".readGcodeFile", target=target, filename=destination, _external=True)
		result = {
			"name": name,
			"path": destination,
			"origin": FileDestinations.LOCAL,
			"refs": {
				"resource": location
			}
		}
		if is_file:
			result["refs"]["download"] = url_for("index", _external=True) + "downloads/files/" + target + "/" + destination

		r = make_response(jsonify(result), 201)
		r.headers["Location"] = location
		return r

	return NO_CONTENT
示例#40
0
def printerToolCommand():
	if not printer.is_operational():
		return make_response("Printer is not operational", 409)

	valid_commands = {
		"select": ["tool"],
		"target": ["targets"],
		"offset": ["offsets"],
		"extrude": ["amount"],
		"flowrate": ["factor"]
	}
	command, data, response = get_json_command_from_request(request, valid_commands)
	if response is not None:
		return response

	validation_regex = re.compile("tool\d+")

	##~~ tool selection
	if command == "select":
		tool = data["tool"]
		if re.match(validation_regex, tool) is None:
			return make_response("Invalid tool: %s" % tool, 400)
		if not tool.startswith("tool"):
			return make_response("Invalid tool for selection: %s" % tool, 400)

		printer.change_tool(tool)

	##~~ temperature
	elif command == "target":
		targets = data["targets"]

		# make sure the targets are valid and the values are numbers
		validated_values = {}
		for tool, value in targets.iteritems():
			if re.match(validation_regex, tool) is None:
				return make_response("Invalid target for setting temperature: %s" % tool, 400)
			if not isinstance(value, (int, long, float)):
				return make_response("Not a number for %s: %r" % (tool, value), 400)
			validated_values[tool] = value

		# perform the actual temperature commands
		for tool in validated_values.keys():
			printer.set_temperature(tool, validated_values[tool])

	##~~ temperature offset
	elif command == "offset":
		offsets = data["offsets"]

		# make sure the targets are valid, the values are numbers and in the range [-50, 50]
		validated_values = {}
		for tool, value in offsets.iteritems():
			if re.match(validation_regex, tool) is None:
				return make_response("Invalid target for setting temperature: %s" % tool, 400)
			if not isinstance(value, (int, long, float)):
				return make_response("Not a number for %s: %r" % (tool, value), 400)
			if not -50 <= value <= 50:
				return make_response("Offset %s not in range [-50, 50]: %f" % (tool, value), 400)
			validated_values[tool] = value

		# set the offsets
		printer.set_temperature_offset(validated_values)

	##~~ extrusion
	elif command == "extrude":
		if printer.is_printing():
			# do not extrude when a print job is running
			return make_response("Printer is currently printing", 409)

		amount = data["amount"]
		if not isinstance(amount, (int, long, float)):
			return make_response("Not a number for extrusion amount: %r" % amount, 400)
		printer.extrude(amount)

	elif command == "flowrate":
		factor = data["factor"]
		if not isinstance(factor, (int, long, float)):
			return make_response("Not a number for flow rate: %r" % factor, 400)
		try:
			printer.flow_rate(factor)
		except ValueError as e:
			return make_response("Invalid value for flow rate: %s" % str(e), 400)

	return NO_CONTENT
示例#41
0
def gcodeFileCommand(filename, target):
	if not target in [FileDestinations.LOCAL, FileDestinations.SDCARD]:
		return make_response("Unknown target: %s" % target, 404)

	if not _verifyFileExists(target, filename):
		return make_response("File not found on '%s': %s" % (target, filename), 404)

	# valid file commands, dict mapping command name to mandatory parameters
	valid_commands = {
		"select": [],
		"slice": []
	}

	command, data, response = get_json_command_from_request(request, valid_commands)
	if response is not None:
		return response

	if command == "select":
		# selects/loads a file
		printAfterLoading = False
		if "print" in data.keys() and data["print"] in valid_boolean_trues:
			if not printer.is_operational():
				return make_response("Printer is not operational, cannot directly start printing", 409)
			printAfterLoading = True

		sd = False
		if target == FileDestinations.SDCARD:
			filenameToSelect = filename
			sd = True
		else:
			filenameToSelect = fileManager.path_on_disk(target, filename)
		printer.select_file(filenameToSelect, sd, printAfterLoading)

	elif command == "slice":
		try:
			if "slicer" in data:
				slicer = data["slicer"]
				del data["slicer"]
				slicer_instance = slicingManager.get_slicer(slicer)

			elif "cura" in slicingManager.registered_slicers:
				slicer = "cura"
				slicer_instance = slicingManager.get_slicer("cura")

			else:
				return make_response("Cannot slice {filename}, no slicer available".format(**locals()), 415)
		except octoprint.slicing.UnknownSlicer as e:
			return make_response("Slicer {slicer} is not available".format(slicer=e.slicer), 400)

		if not any([octoprint.filemanager.valid_file_type(filename, type=source_file_type) for source_file_type in slicer_instance.get_slicer_properties().get("source_file_types", ["model"])]):
			return make_response("Cannot slice {filename}, not a model file".format(**locals()), 415)

		if slicer_instance.get_slicer_properties().get("same_device", True) and (printer.is_printing() or printer.is_paused()):
			# slicer runs on same device as OctoPrint, slicing while printing is hence disabled
			return make_response("Cannot slice on {slicer} while printing due to performance reasons".format(**locals()), 409)

		if "destination" in data and data["destination"]:
			destination = data["destination"]
			del data["destination"]
		elif "gcode" in data and data["gcode"]:
			destination = data["gcode"]
			del data["gcode"]
		else:
			import os
			name, _ = os.path.splitext(filename)
			destination = name + "." + slicer_instance.get_slicer_properties().get("destination_extensions", ["gco", "gcode", "g"])[0]

		# prohibit overwriting the file that is currently being printed
		currentOrigin, currentFilename = _getCurrentFile()
		if currentFilename == destination and currentOrigin == target and (printer.is_printing() or printer.is_paused()):
			make_response("Trying to slice into file that is currently being printed: %s" % destination, 409)

		if "profile" in data.keys() and data["profile"]:
			profile = data["profile"]
			del data["profile"]
		else:
			profile = None

		if "printerProfile" in data.keys() and data["printerProfile"]:
			printerProfile = data["printerProfile"]
			del data["printerProfile"]
		else:
			printerProfile = None

		if "position" in data.keys() and data["position"] and isinstance(data["position"], dict) and "x" in data["position"] and "y" in data["position"]:
			position = data["position"]
			del data["position"]
		else:
			position = None

		select_after_slicing = False
		if "select" in data.keys() and data["select"] in valid_boolean_trues:
			if not printer.is_operational():
				return make_response("Printer is not operational, cannot directly select for printing", 409)
			select_after_slicing = True

		print_after_slicing = False
		if "print" in data.keys() and data["print"] in valid_boolean_trues:
			if not printer.is_operational():
				return make_response("Printer is not operational, cannot directly start printing", 409)
			select_after_slicing = print_after_slicing = True

		override_keys = [k for k in data if k.startswith("profile.") and data[k] is not None]
		overrides = dict()
		for key in override_keys:
			overrides[key[len("profile."):]] = data[key]

		def slicing_done(target, gcode_name, select_after_slicing, print_after_slicing):
			if select_after_slicing or print_after_slicing:
				sd = False
				if target == FileDestinations.SDCARD:
					filenameToSelect = gcode_name
					sd = True
				else:
					filenameToSelect = fileManager.path_on_disk(target, gcode_name)
				printer.select_file(filenameToSelect, sd, print_after_slicing)

		try:
			fileManager.slice(slicer, target, filename, target, destination,
			                  profile=profile,
			                  printer_profile_id=printerProfile,
			                  position=position,
			                  overrides=overrides,
			                  callback=slicing_done,
			                  callback_args=(target, destination, select_after_slicing, print_after_slicing))
		except octoprint.slicing.UnknownProfile:
			return make_response("Profile {profile} doesn't exist".format(**locals()), 400)

		files = {}
		location = url_for(".readGcodeFile", target=target, filename=destination, _external=True)
		result = {
			"name": destination,
			"origin": FileDestinations.LOCAL,
			"refs": {
				"resource": location,
				"download": url_for("index", _external=True) + "downloads/files/" + target + "/" + destination
			}
		}

		r = make_response(jsonify(result), 202)
		r.headers["Location"] = location
		return r

	return NO_CONTENT
示例#42
0
def utilTestPath():
	valid_commands = dict(
		path=["path"],
		url=["url"],
		server=["host", "port"]
	)

	command, data, response = get_json_command_from_request(request, valid_commands)
	if response is not None:
		return response

	if command == "path":
		import os
		from octoprint.util.paths import normalize

		path = normalize(data["path"])
		if not path:
			return jsonify(path=path, exists=False, typeok=False, access=False, result=False)

		check_type = None
		check_access = []

		if "check_type" in data and data["check_type"] in ("file", "dir"):
			check_type = data["check_type"]

		if "check_access" in data:
			request_check_access = data["check_access"]
			if not isinstance(request_check_access, list):
				request_check_access = list(request_check_access)

			check_access = [check for check in request_check_access if check in ("r", "w", "x")]

		exists = os.path.exists(path)

		# check if path exists
		type_mapping = dict(file=os.path.isfile, dir=os.path.isdir)
		if check_type:
			typeok = type_mapping[check_type](path)
		else:
			typeok = exists

		# check if path allows requested access
		access_mapping = dict(r=os.R_OK, w=os.W_OK, x=os.X_OK)
		if check_access:
			access = os.access(path, reduce(lambda x, y: x | y, map(lambda a: access_mapping[a], check_access)))
		else:
			access = exists

		return jsonify(path=path, exists=exists, typeok=typeok, access=access, result=exists and typeok and access)

	elif command == "url":
		import requests

		class StatusCodeRange(object):
			def __init__(self, start=None, end=None):
				self.start = start
				self.end = end

			def __contains__(self, item):
				if not isinstance(item, int):
					return False
				if self.start and self.end:
					return self.start <= item < self.end
				elif self.start:
					return self.start <= item
				elif self.end:
					return item < self.end
				else:
					return False

			def as_dict(self):
				return dict(
					start=self.start,
					end=self.end
				)

		status_ranges = dict(
			informational=StatusCodeRange(start=100,end=200),
			success=StatusCodeRange(start=200,end=300),
			redirection=StatusCodeRange(start=300,end=400),
			client_error=StatusCodeRange(start=400,end=500),
			server_error=StatusCodeRange(start=500,end=600),
			normal=StatusCodeRange(end=400),
			error=StatusCodeRange(start=400,end=600),
			any=StatusCodeRange(start=100),
			timeout=StatusCodeRange(start=0, end=1)
		)

		url = data["url"]
		method = data.get("method", "HEAD")
		timeout = 3.0
		check_status = [status_ranges["normal"]]

		if "timeout" in data:
			try:
				timeout = float(data["timeout"])
			except:
				return make_response("{!r} is not a valid value for timeout (must be int or float)".format(data["timeout"]), 400)

		if "status" in data:
			request_status = data["status"]
			if not isinstance(request_status, list):
				request_status = [request_status]

			check_status = []
			for rs in request_status:
				if isinstance(rs, int):
					check_status.append([rs])
				else:
					if rs in status_ranges:
						check_status.append(status_ranges[rs])
					else:
						code = requests.codes[rs]
						if code is not None:
							check_status.append([code])

		try:
			response = requests.request(method=method, url=url, timeout=timeout)
			status = response.status_code
		except:
			status = 0

		result = dict(
			url=url,
			status=status,
			result=any(map(lambda x: status in x, check_status))
		)

		if "response" in data and (data["response"] in valid_boolean_trues or data["response"] in ("json", "bytes")):

			import base64
			content = base64.standard_b64encode(response.content)

			if data["response"] == "json":
				try:
					content = response.json()
				except:
					logging.getLogger(__name__).exception("Couldn't convert response to json")
					result["result"] = False

			result["response"] = dict(
				headers=dict(response.headers),
				content=content
			)
		return jsonify(**result)

	elif command == "server":
		host = data["host"]
		try:
			port = int(data["port"])
		except:
			return make_response("{!r} is not a valid value for port (must be int)".format(data["port"]), 400)
		
		timeout = 3.05
		if "timeout" in data:
			try:
				timeout = float(data["timeout"])
			except:
				return make_response("{!r} is not a valid value for timeout (must be int or float)".format(data["timeout"]), 400)
		
		protocol = data.get("protocol", "tcp")
		if protocol not in ("tcp", "udp"):
			return make_response("{!r} is not a valid value for protocol, must be tcp or udp".format(protocol), 400)
		
		from octoprint.util import server_reachable
		reachable = server_reachable(host, port, timeout=timeout, proto=protocol)
		
		result = dict(host=host,
		              port=port,
		              protocol=protocol,
		              result=reachable)
		
		return jsonify(**result)
示例#43
0
	def gcodeFileCommand(self, target, filename):
		if target not in [FileDestinations.LOCAL]:
			return make_response("Unknown target: %s" % target, 404)

		if not self._settings.global_get_boolean(["feature", "sdSupport"]):
			return make_response("SD card support is disabled", 404)

		# valid file commands, dict mapping command name to mandatory parameters
		valid_commands = {
			"uploadSd": []
		}

		command, data, response = get_json_command_from_request(request, valid_commands)
		if response is not None:
			return response

		if command == "uploadSd":
			from octoprint.server.api.files import _verifyFolderExists, _verifyFileExists
			if not _verifyFileExists(FileDestinations.LOCAL, filename):
				return make_response("File not found on '%s': %s" % (FileDestinations.LOCAL, filename), 404)

			from octoprint.filemanager import valid_file_type
			if not valid_file_type(filename, type="machinecode"):
				return make_response("Cannot upload {filename} to SD, not a machinecode file".format(**locals()), 415)

			# validate that all preconditions for SD upload are met before attempting it
			if not (self._printer.is_operational() and not (self._printer.is_printing() or self._printer.is_paused())):
				return make_response("Can not upload to SD card, printer is either not operational or already busy",
									 409)
			if not self._printer.is_sd_ready():
				return make_response("Can not upload to SD card, not yet initialized", 409)

			# determine current job
			currentFilename = None
			currentFullPath = None
			currentOrigin = None
			currentJob = self._printer.get_current_job()
			if currentJob is not None and "file" in currentJob.keys():
				currentJobFile = currentJob["file"]
				if currentJobFile is not None and "name" in currentJobFile.keys() and "origin" in currentJobFile.keys() and \
								currentJobFile["name"] is not None and currentJobFile["origin"] is not None:
					currentPath, currentFilename = self._file_manager.split_path(FileDestinations.LOCAL,
																				 currentJobFile["name"])
					currentOrigin = currentJobFile["origin"]

			selectAfterUpload = "select" in request.values.keys() and request.values["select"] in valid_boolean_trues
			printAfterSelect = "print" in request.values.keys() and request.values["print"] in valid_boolean_trues

			filePath, fileName = self._file_manager.sanitize(FileDestinations.LOCAL, filename)
			fullPath = self._file_manager.join_path(FileDestinations.LOCAL, filePath, fileName)

			def selectAndOrPrint(filename, absFilename, destination):
				"""
				Callback for when the file is ready to be selected and optionally printed. For SD file uploads this is only
				the case after they have finished streaming to the printer, which is why this callback is also used
				for the corresponding call to addSdFile.

				Selects the just uploaded file if either selectAfterUpload or printAfterSelect are True, or if the
				exact file is already selected, such reloading it.
				"""
				if selectAfterUpload or printAfterSelect or (
								currentFilename == filename and currentOrigin == destination):
					self._printer.select_file(absFilename, destination == FileDestinations.SDCARD, printAfterSelect)

			sdFilename = self._printer.add_sd_file(fileName, fullPath, selectAndOrPrint)

			from octoprint.events import Events
			self._event_bus.fire(Events.UPLOAD, {"file": sdFilename, "target": FileDestinations.SDCARD})

			location = url_for("api.readGcodeFile", target=FileDestinations.SDCARD, filename=sdFilename, _external=True)
			files = {
				FileDestinations.SDCARD: {
					"name": sdFilename,
					"origin": FileDestinations.SDCARD,
					"refs": {
						"resource": location
					}
				}
			}

			r = make_response(jsonify(files=files, done=True), 201)
			r.headers["Location"] = location
			return r