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})
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
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
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)
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
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
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
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
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
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
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)
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
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
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
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
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})
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)
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
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)
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})
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
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
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
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
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
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
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)
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
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
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)
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
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
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
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)
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
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
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
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
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
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)
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