예제 #1
0
파일: api.py 프로젝트: d42/octoprint-fork
def apiLoad():
    logger = logging.getLogger(__name__)

    if not settings.get("api", "enabled"):
        abort(401)

    if not "apikey" in request.values.keys():
        abort(401)

    if request.values["apikey"] != settings.get("api", "key"):
        abort(403)

    if not "file" in request.files.keys():
        abort(400)

    # Perform an upload
    file = request.files["file"]
    if not gcodefiles.isGcodeFileName(file.filename):
        abort(400)

    destination = FileDestinations.LOCAL
    filename, done = gcodeManager.addFile(file, destination)
    if filename is None:
        logger.warn("Upload via API failed")
        abort(500)

    # Immediately perform a file select and possibly print too
    printAfterSelect = False
    if "print" in request.values.keys() and request.values["print"] in valid_boolean_trues:
        printAfterSelect = True
    filepath = gcodeManager.getAbsolutePath(filename)
    if filepath is not None:
        printer.selectFile(filepath, False, printAfterSelect)
    return jsonify(SUCCESS)
예제 #2
0
def init_connectivity_checker(settings, event_manager):
    from octoprint.events import Events
    from octoprint.util import ConnectivityChecker

    # start regular check if we are connected to the internet
    connectivityEnabled = settings.getBoolean(
        ["server", "onlineCheck", "enabled"])
    connectivityInterval = settings.getInt(
        ["server", "onlineCheck", "interval"])
    connectivityHost = settings.get(["server", "onlineCheck", "host"])
    connectivityPort = settings.getInt(["server", "onlineCheck", "port"])
    connectivityName = settings.get(["server", "onlineCheck", "name"])

    def on_connectivity_change(old_value,
                               new_value,
                               connection_working=None,
                               resolution_working=None):
        event_manager.fire(Events.CONNECTIVITY_CHANGED,
                           payload=dict(old=old_value,
                                        new=new_value,
                                        connection=connection_working,
                                        resolution=resolution_working))

    connectivityChecker = ConnectivityChecker(connectivityInterval,
                                              connectivityHost,
                                              port=connectivityPort,
                                              name=connectivityName,
                                              enabled=connectivityEnabled,
                                              on_change=on_connectivity_change)
    connectivityChecker.check_immediately()
    connectivityChecker.log_full_report()

    return connectivityChecker
예제 #3
0
def getConnectionOptions():
    """
     Retrieves the available ports, baudrates, prefered port and baudrate for connecting to the printer.
    """
    return {
        "ports": comm.serialList(),
        "baudrates": comm.baudrateList(),
        "portPreference": settings.get("serial", "port"),
        "baudratePreference": settings.get("serial", "baudrate"),
        "autoconnect": settings.get("serial", "autoconnect")
    }
예제 #4
0
파일: api.py 프로젝트: d42/octoprint-fork
def apiPrinterState():
    if not settings.get("api", "enabled"):
        abort(401)

    if not "apikey" in request.values.keys():
        abort(401)

    if request.values["apikey"] != settings.get("api", "key"):
        abort(403)

    currentData = printer.getCurrentData()
    currentData.update({
        "temperatures": printer.getCurrentTemperatures()
    })
    return jsonify(currentData)
예제 #5
0
    def _initSubscriptions(self, triggerType):
        """
        Subscribes all events as defined in "events > $triggerType > subscriptions" in the settings with their
        respective commands.
        """
        if triggerType in settings.disabled_events:
            return

        if triggerType not in settings.enabled_events:
            return

        eventsToSubscribe = []
        for subscription in settings.get("events", triggerType + "_subscriptions"):
            #XXX: I have no idea how this works yet
            if not "event" in subscription.keys() or not "command" in subscription.keys():
                self._logger.info(
                    "Invalid %s, missing either event or command: %r" % (triggerType, subscription))
                continue

            event = subscription["event"]
            command = subscription["command"]

            if not event in self._subscriptions.keys():
                self._subscriptions[event] = []
            self._subscriptions[event].append(command)

            if not event in eventsToSubscribe:
                eventsToSubscribe.append(event)

        self.subscribe(eventsToSubscribe)
예제 #6
0
    def _initLogging(self, debug):
        config = {
            "version": 1,
            "formatters": {
                "simple": {
                    "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
                }
            },
            "handlers": {
                "console": {
                    "class": "logging.StreamHandler",
                    "level": "DEBUG",
                    "formatter": "simple",
                    "stream": "ext://sys.stdout"
                },
                "file": {
                    "class": "logging.handlers.TimedRotatingFileHandler",
                    "level": "DEBUG",
                    "formatter": "simple",
                    "when": "D",
                    "backupCount": "1",
                    "filename": os.path.join(settings.getpath("logs"), "octoprint.log")
                },
                "serialFile": {
                    "class": "logging.handlers.RotatingFileHandler",
                    "level": "DEBUG",
                    "formatter": "simple",
                    # let's limit the serial log to 2MB in size
                    "maxBytes": 2 * 1024 * 1024,
                    "filename": os.path.join(settings.getpath("logs"), "serial.log")
                }
            },
            "loggers": {
                #"octoprint.timelapse": {
                #	"level": "DEBUG"
                #},
                #"octoprint.events": {
                #	"level": "DEBUG"
                #},
                "SERIAL": {
                    "level": "CRITICAL",
                    "handlers": ["serialFile"],
                    "propagate": False
                }
            },
            "root": {
                "level": "INFO",
                "handlers": ["console", "file"]
            }
        }

        if debug:
            config["root"]["level"] = "DEBUG"

        logging.config.dictConfig(config)

        if settings.get("serial", "log"):
            # enable debug logging to serial.log
            logging.getLogger("SERIAL").setLevel(logging.DEBUG)
            logging.getLogger("SERIAL").debug("Enabling serial logging")
예제 #7
0
    def addFile(self, file, destination, uploadCallback=None):
        """
        Adds the given file for the given destination to the systems. Takes care of slicing if enabled and
        necessary.

        If the file's processing won't be finished directly with the return from this method but happen
        asynchronously in the background (e.g. due to slicing), returns a tuple containing the just added file's
        filename and False. Otherwise returns a tuple (filename, True).
        """
        if not file or not destination:
            return None, True

        curaEnabled = settings.get("cura", "enabled")
        filename = file.filename

        absolutePath = self.getAbsolutePath(filename, mustExist=False)
        gcode = isGcodeFileName(filename)

        if absolutePath is None or (not curaEnabled and not gcode):
            return None, True

        file.save(absolutePath)

        if gcode:
            return self.processGcode(absolutePath, destination, uploadCallback), True
        else:
            if curaEnabled and isSTLFileName(filename):
                self.processStl(absolutePath, destination, uploadCallback)
            return filename, False
예제 #8
0
    def processStl(self, absolutePath, destination, uploadCallback=None):
        from octoprint.slicers.cura import CuraFactory

        cura = CuraFactory.create_slicer()
        gcodePath = genGcodeFileName(absolutePath)
        config = settings.get("cura", "config")

        slicingStart = time.time()

        def stlProcessed(stlPath, gcodePath, error=None):
            if error:
                eventManager().fire("SlicingFailed", {"stl": self._getBasicFilename(
                    stlPath), "gcode": self._getBasicFilename(gcodePath), "reason": error})
                if os.path.exists(stlPath):
                    os.remove(stlPath)
            else:
                slicingStop = time.time()
                eventManager().fire("SlicingDone", {"stl": self._getBasicFilename(
                    stlPath), "gcode": self._getBasicFilename(gcodePath), "time": "%.2f" % (slicingStop - slicingStart)})
                self.processGcode(gcodePath, destination, uploadCallback)

        eventManager().fire("SlicingStarted", {"stl": self._getBasicFilename(
            absolutePath), "gcode": self._getBasicFilename(gcodePath)})
        cura.process_file(
            config, gcodePath, absolutePath, stlProcessed, [absolutePath, gcodePath])
예제 #9
0
def jog():
    if not printer.isOperational() or printer.isPrinting():
        # do not jog when a print job is running or we don't have a connection
        return jsonify(SUCCESS)

    (movementSpeedX, movementSpeedY, movementSpeedZ, movementSpeedE) = (
            settings.get('movement_speed', s) for s in 'xyze')
    if "x" in request.values.keys():
        # jog x
        x = request.values["x"]
        printer.commands(["G91", "G1 X%s F%d" % (x, movementSpeedX), "G90"])
    if "y" in request.values.keys():
        # jog y
        y = request.values["y"]
        printer.commands(["G91", "G1 Y%s F%d" % (y, movementSpeedY), "G90"])
    if "z" in request.values.keys():
        # jog z
        z = request.values["z"]
        printer.commands(["G91", "G1 Z%s F%d" % (z, movementSpeedZ), "G90"])
    if "homeXY" in request.values.keys():
        # home x/y
        printer.command("G28 X0 Y0")
    if "homeZ" in request.values.keys():
        # home z
        printer.command("G28 Z0")
    if "extrude" in request.values.keys():
        # extrude/retract
        length = request.values["extrude"]
        printer.commands(
            ["G91", "G1 E%s F%d" % (length, movementSpeedE), "G90"])
    return jsonify(SUCCESS)
예제 #10
0
def login():
    if octoprint.server.userManager is not None and "user" in request.values.keys() and "pass" in request.values.keys():
        username = request.values["user"]
        password = request.values["pass"]

        if "remember" in request.values.keys() and request.values["remember"] == "true":
            remember = True
        else:
            remember = False

        user = octoprint.server.userManager.findUser(username)
        if user is not None:
            if user.check_password(octoprint.users.UserManager.createPasswordHash(password)):
                login_user(user, remember=remember)
                identity_changed.send(
                    current_app._get_current_object(), identity=Identity(user.get_id()))
                return jsonify(user.asDict())
        return make_response(("User unknown or password incorrect", 401, []))
    elif "passive" in request.values.keys():
        user = current_user
        if user is not None and not user.is_anonymous():
            identity_changed.send(
                current_app._get_current_object(), identity=Identity(user.get_id()))
            return jsonify(user.asDict())
        elif (s.get("access_control", "autologin_local")
                and s.get("access_control", "autologin_as") is not None
                and s.get("access_control", "local_networks") is not None):

            autologinAs = s.get("access_control", "autologin_as")
            localNetworks = netaddr.IPSet([])
            for ip in s.get("access_control", "local_networks"):
                localNetworks.add(ip)

            try:
                remoteAddr = util.getRemoteAddress(request)
                if netaddr.IPAddress(remoteAddr) in localNetworks:
                    user = octoprint.server.userManager.findUser(autologinAs)
                    if user is not None:
                        login_user(user)
                        identity_changed.send(
                            current_app._get_current_object(), identity=Identity(user.get_id()))
                        return jsonify(user.asDict())
            except:
                logger = logging.getLogger(__name__)
                logger.exception(
                    "Could not autologin user %s for networks %r" % (autologinAs, localNetworks))
    return jsonify(SUCCESS)
예제 #11
0
def index():
    branch = None
    commit = None
    try:
        branch, commit = util.getGitInfo()
    except:
        pass

    return render_template(
        "index.jinja2",
        webcamStream=settings.get("webcam", "stream"),
        enableTimelapse=(settings.get("webcam", "snapshot") is not None and settings.get(
            "webcam", "ffmpeg") is not None),
        enableGCodeVisualizer=settings.get("features", "gcode_visualizer"),
        enableTemperatureGraph=settings.get("features", "temperature_graph"),
        #enableSystemMenu=settings.get(["system"]) is not None and settings.get(
            #["system", "actions"]) is not None and len(settings.get(["system", "actions"])) > 0,
        #XXX: restore this
        enableSystemMenu = False,
        enableAccessControl=userManager is not None,
        enableSdSupport=settings.get("features", "sd_support"),
        firstRun=settings.get("server", "first_run") and (
            userManager is None or not userManager.hasBeenCustomized()),
        debug=debug,
        gitBranch=branch,
        gitCommit=commit
    )
예제 #12
0
파일: util.py 프로젝트: d42/octoprint-fork
    def __call__(self, environ, start_response):
        script_name = environ.get('HTTP_X_SCRIPT_NAME', '')
        if not script_name:
            script_name = settings.get("server", "base_url")

        if script_name:
            environ['SCRIPT_NAME'] = script_name
            path_info = environ['PATH_INFO']
            if path_info.startswith(script_name):
                environ['PATH_INFO'] = path_info[len(script_name):]

        scheme = environ.get('HTTP_X_SCHEME', '')
        if not scheme:
            scheme = settings.get("server", "scheme")

        if scheme:
            environ['wsgi.url_scheme'] = scheme
        return self.app(environ, start_response)
예제 #13
0
파일: users.py 프로젝트: d42/octoprint-fork
    def __init__(self):
        UserManager.__init__(self)

        userfile = settings.get("access_control", "userfile")
        if not userfile:
            userfile = os.path.join(settings.settings_dir, "users.yaml")
        self._userfile = userfile
        self._users = {}
        self._dirty = False

        self._customized = None
        self._load()
예제 #14
0
def sdCommand():
    if not settings.get("feature", "sd_support") or not printer.isOperational() or printer.isPrinting():
        return jsonify(SUCCESS)

    if "command" in request.values.keys():
        command = request.values["command"]
        if command == "init":
            printer.initSdCard()
        elif command == "refresh":
            printer.refreshSdFiles()
        elif command == "release":
            printer.releaseSdCard()

    return jsonify(SUCCESS)
예제 #15
0
    def boxId(self):
        if not self._boxId:
            import os
            boxIdFile = "%s/box-id" % os.path.dirname(
                self._settings._configfile)

            if os.path.exists(boxIdFile):
                with open(boxIdFile, 'r') as f:
                    self._boxId = f.read()
            if not self._boxId:
                self._boxId = settings.get(['setup', 'machineId'])
            if not self._boxId:
                raise RuntimeError('BoxId not present, please login')

        return self._boxId
예제 #16
0
    def _getStateFlags(self):
        if not settings.get("features", "sd_support") or self._comm is None:
            sdReady = False
        else:
            sdReady = self._comm.isSdReady()

        return {
            "operational": self.isOperational(),
            "printing": self.isPrinting(),
            "closedOrError": self.isClosedOrError(),
            "error": self.isError(),
            "paused": self.isPaused(),
            "ready": self.isReady(),
            "sdReady": sdReady
        }
예제 #17
0
def init_connectivity_checker(settings, event_manager):
	from octoprint.events import Events
	from octoprint.util import ConnectivityChecker

	# start regular check if we are connected to the internet
	connectivityEnabled = settings.getBoolean(["server", "onlineCheck", "enabled"])
	connectivityInterval = settings.getInt(["server", "onlineCheck", "interval"])
	connectivityHost = settings.get(["server", "onlineCheck", "host"])
	connectivityPort = settings.getInt(["server", "onlineCheck", "port"])

	def on_connectivity_change(old_value, new_value):
		event_manager.fire(Events.CONNECTIVITY_CHANGED, payload=dict(old=old_value, new=new_value))

	connectivityChecker = ConnectivityChecker(connectivityInterval,
	                                          connectivityHost,
	                                          port=connectivityPort,
	                                          enabled=connectivityEnabled,
	                                          on_change=on_connectivity_change)

	return connectivityChecker
예제 #18
0
    def __init__(self):
        self._logger = logging.getLogger(__name__)
        self._imageNumber = None
        self._inTimelapse = False
        self._gcodeFile = None

        self._captureDir = settings.getpath("timelapse_tmp")
        self._movieDir = settings.getpath("timelapse")
        self._snapshotUrl = settings.get("webcam", "snapshot")

        self._renderThread = None
        self._captureMutex = threading.Lock()

        # subscribe events
        eventManager().subscribe("PrintStarted", self.onPrintStarted)
        eventManager().subscribe("PrintFailed", self.onPrintDone)
        eventManager().subscribe("PrintDone", self.onPrintDone)
        eventManager().subscribe("PrintResumed", self.onPrintResumed)
        for (event, callback) in self.eventSubscriptions():
            eventManager().subscribe(event, callback)
예제 #19
0
def performSystemAction():
    logger = logging.getLogger(__name__)
    if request.values.has_key("action"):
        action = request.values["action"]
        availableActions = s.get("system", "actions")
        for availableAction in availableActions:
            if availableAction["action"] == action:
                logger.info("Performing command: %s" %
                            availableAction["command"])
                try:
                    subprocess.check_output(
                        availableAction["command"], shell=True)
                except subprocess.CalledProcessError as e:
                    logger.warn(
                        "Command failed with return code %i: %s" % (e.returncode, e.message))
                    return make_response(("Command failed with return code %i: %s" % (e.returncode, e.message), 500, []))
                except Exception as ex:
                    logger.exception("Command failed")
                    return make_response(("Command failed: %r" % ex, 500, []))
    return jsonify(SUCCESS)
예제 #20
0
def init_connectivity_checker(settings, event_manager):
	from octoprint.events import Events
	from octoprint.util import ConnectivityChecker

	# start regular check if we are connected to the internet
	connectivityEnabled = settings.getBoolean(["server", "onlineCheck", "enabled"])
	connectivityInterval = settings.getInt(["server", "onlineCheck", "interval"])
	connectivityHost = settings.get(["server", "onlineCheck", "host"])
	connectivityPort = settings.getInt(["server", "onlineCheck", "port"])

	def on_connectivity_change(old_value, new_value):
		event_manager.fire(Events.CONNECTIVITY_CHANGED, payload=dict(old=old_value, new=new_value))

	connectivityChecker = ConnectivityChecker(connectivityInterval,
	                                          connectivityHost,
	                                          port=connectivityPort,
	                                          enabled=connectivityEnabled,
	                                          on_change=on_connectivity_change)

	return connectivityChecker
예제 #21
0
def firstRunSetup():
    if not s.get("server", "first_run"):
        abort(403)

    if "ac" in request.values.keys() and request.values["ac"] in valid_boolean_trues and \
            "user" in request.values.keys() and "pass1" in request.values.keys() and \
            "pass2" in request.values.keys() and request.values["pass1"] == request.values["pass2"]:
        # configure access control
        s.set("access_control", "enabled", True)
        octoprint.server.userManager.addUser(
            request.values["user"], request.values["pass1"], True, ["user", "admin"])
        s.set("server", "first_run", False)
    elif "ac" in request.values.keys() and not request.values["ac"] in valid_boolean_trues:
        # disable access control
        s.set("access_control", "enabled", False)
        s.set("server", "first_run", False)

        loginManager.anonymous_user = octoprint.users.DummyUser
        principals.identity_loaders.appendleft(
            octoprint.users.dummy_identity_loader)

    s.save()
    return jsonify(SUCCESS)
예제 #22
0
파일: users.py 프로젝트: d42/octoprint-fork
 def __init__(self):
     super(HackerspaceUserManager, self).__init__()
     self.group = settings.get("access_control", "group")
예제 #23
0
def get_plugin_blacklist(settings, connectivity_checker=None):
	import requests
	import os
	import time
	import yaml

	from octoprint.util import bom_aware_open
	from octoprint.util.version import is_octoprint_compatible

	logger = log.getLogger(__name__ + ".startup")

	if connectivity_checker is not None and not connectivity_checker.online:
		logger.info("We don't appear to be online, not fetching plugin blacklist")
		return []

	def format_blacklist(entries):
		format_entry = lambda x: "{} ({})".format(x[0], x[1]) if isinstance(x, (list, tuple)) and len(x) == 2 \
			else "{} (any)".format(x)
		return ", ".join(map(format_entry, entries))

	def process_blacklist(entries):
		result = []

		if not isinstance(entries, list):
			return result

		for entry in entries:
			if not "plugin" in entry:
				continue

			if "octoversions" in entry and not is_octoprint_compatible(*entry["octoversions"]):
				continue

			if "version" in entry:
				logger.debug("Blacklisted plugin: {}, version: {}".format(entry["plugin"], entry["version"]))
				result.append((entry["plugin"], entry["version"]))
			elif "versions" in entry:
				logger.debug("Blacklisted plugin: {}, versions: {}".format(entry["plugin"], ", ".join(entry["versions"])))
				for version in entry["versions"]:
					result.append((entry["plugin"], version))
			else:
				logger.debug("Blacklisted plugin: {}".format(entry["plugin"]))
				result.append(entry["plugin"])

		return result

	def fetch_blacklist_from_cache(path, ttl):
		if not os.path.isfile(path):
			return None

		if os.stat(path).st_mtime + ttl < time.time():
			return None

		with bom_aware_open(path, encoding="utf-8", mode="r") as f:
			result = yaml.safe_load(f)

		if isinstance(result, list):
			return result

	def fetch_blacklist_from_url(url, timeout=3, cache=None):
		result = []
		try:
			r = requests.get(url, timeout=timeout)
			result = process_blacklist(r.json())

			if cache is not None:
				try:
					with bom_aware_open(cache, encoding="utf-8", mode="w") as f:
						yaml.safe_dump(result, f)
				except:
					logger.info("Fetched plugin blacklist but couldn't write it to its cache file.")
		except:
			logger.info("Unable to fetch plugin blacklist from {}, proceeding without it.".format(url))
		return result

	try:
		# first attempt to fetch from cache
		cache_path = os.path.join(settings.getBaseFolder("data"), "plugin_blacklist.yaml")
		ttl = settings.getInt(["server", "pluginBlacklist", "ttl"])
		blacklist = fetch_blacklist_from_cache(cache_path, ttl)

		if blacklist is None:
			# no result from the cache, let's fetch it fresh
			url = settings.get(["server", "pluginBlacklist", "url"])
			timeout = settings.getFloat(["server", "pluginBlacklist", "timeout"])
			blacklist = fetch_blacklist_from_url(url, timeout=timeout, cache=cache_path)

		if blacklist is None:
			# still now result, so no blacklist
			blacklist = []

		if blacklist:
			logger.info("Blacklist processing done, "
			            "adding {} blacklisted plugin versions: {}".format(len(blacklist),
			                                                               format_blacklist(blacklist)))
		else:
			logger.info("Blacklist processing done")

		return blacklist
	except:
		logger.exception("Something went wrong while processing the plugin blacklist. Proceeding without it.")
예제 #24
0
def init_pluginsystem(settings, safe_mode=False, ignore_blacklist=True, connectivity_checker=None):
	"""Initializes the plugin manager based on the settings."""

	import os

	logger = log.getLogger(__name__ + ".startup")

	plugin_folders = [(os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), "plugins")), True),
	                  settings.getBaseFolder("plugins")]
	plugin_entry_points = ["octoprint.plugin"]
	plugin_disabled_list = settings.get(["plugins", "_disabled"])

	plugin_blacklist = []
	if not ignore_blacklist and settings.getBoolean(["server", "pluginBlacklist", "enabled"]):
		plugin_blacklist = get_plugin_blacklist(settings, connectivity_checker=connectivity_checker)

	plugin_validators = []
	if safe_mode:
		def validator(phase, plugin_info):
			if phase in ("before_import", "before_load", "before_enable"):
				setattr(plugin_info, "safe_mode_victim", not plugin_info.bundled)
				if not plugin_info.bundled:
					return False
			return True
		plugin_validators.append(validator)

	from octoprint.plugin import plugin_manager
	pm = plugin_manager(init=True,
	                    plugin_folders=plugin_folders,
	                    plugin_entry_points=plugin_entry_points,
	                    plugin_disabled_list=plugin_disabled_list,
	                    plugin_blacklist=plugin_blacklist,
	                    plugin_validators=plugin_validators)

	settings_overlays = dict()
	disabled_from_overlays = dict()

	def handle_plugin_loaded(name, plugin):
		if plugin.instance and hasattr(plugin.instance, "__plugin_settings_overlay__"):
			plugin.needs_restart = True

			# plugin has a settings overlay, inject it
			overlay_definition = getattr(plugin.instance, "__plugin_settings_overlay__")
			if isinstance(overlay_definition, (tuple, list)):
				overlay_definition, order = overlay_definition
			else:
				order = None

			overlay = settings.load_overlay(overlay_definition)

			if "plugins" in overlay and "_disabled" in overlay["plugins"]:
				disabled_plugins = overlay["plugins"]["_disabled"]
				del overlay["plugins"]["_disabled"]
				disabled_from_overlays[name] = (disabled_plugins, order)

			settings_overlays[name] = overlay
			logger.debug("Found settings overlay on plugin {}".format(name))

	def handle_plugins_loaded(startup=False, initialize_implementations=True, force_reload=None):
		if not startup:
			return

		sorted_disabled_from_overlays = sorted([(key, value[0], value[1]) for key, value in disabled_from_overlays.items()], key=lambda x: (x[2] is None, x[2], x[0]))

		disabled_list = pm.plugin_disabled_list
		already_processed = []
		for name, addons, _ in sorted_disabled_from_overlays:
			if not name in disabled_list and not name.endswith("disabled"):
				for addon in addons:
					if addon in disabled_list:
						continue

					if addon in already_processed:
						logger.info("Plugin {} wants to disable plugin {}, but that was already processed".format(name, addon))

					if not addon in already_processed and not addon in disabled_list:
						disabled_list.append(addon)
						logger.info("Disabling plugin {} as defined by plugin {}".format(addon, name))
				already_processed.append(name)

	def handle_plugin_enabled(name, plugin):
		if name in settings_overlays:
			settings.add_overlay(settings_overlays[name])
			logger.info("Added settings overlay from plugin {}".format(name))

	pm.on_plugin_loaded = handle_plugin_loaded
	pm.on_plugins_loaded = handle_plugins_loaded
	pm.on_plugin_enabled = handle_plugin_enabled
	pm.reload_plugins(startup=True, initialize_implementations=False)
	return pm
예제 #25
0
    def write(self, data):
        if self.readList is None:
            return

        data = data.strip()

        # strip checksum
        if "*" in data:
            data = data[:data.rfind("*")]
            self.currentLine += 1
        elif settings.get("virtual_printer", "force_checksum"):
            self.readList.append("Error: Missing checksum")
            return

        # track N = N + 1
        if data.startswith("N") and "M110" in data:
            linenumber = int(re.search("N([0-9]+)", data).group(1))
            self.lastN = linenumber
            self.currentLine = linenumber
            return
        elif data.startswith("N"):
            linenumber = int(re.search("N([0-9]+)", data).group(1))
            expected = self.lastN + 1
            if linenumber != expected:
                self.readList.append(
                    "Error: expected line %d got %d" % (expected, linenumber))
                self.readList.append("Resend:%d" % expected)
                if settings.get("virtual_printer", "ok_after_resend"):
                    self.readList.append("ok")
                return
            elif self.currentLine == 100:
                # simulate a resend at line 100 of the last 5 lines
                self.lastN = 94
                self.readList.append(
                    "Error: Line Number is not Last Line Number\n")
                self.readList.append("rs %d\n" % (self.currentLine - 5))
                if settings.get("virtual_printer", "ok_after_resend"):
                    self.readList.append("ok")
                return
            else:
                self.lastN = linenumber
            data = data.split(None, 1)[1].strip()

        data += "\n"

        # shortcut for writing to SD
        if self._writingToSd and not self._selectedSdFile is None and not "M29" in data:
            with open(self._selectedSdFile, "a") as f:
                f.write(data)
            self._sendOk()
            return

        # print "Send: %s" % (data.rstrip())
        if 'M104' in data or 'M109' in data:
            try:
                self.targetTemp = float(re.search('S([0-9]+)', data).group(1))
            except:
                pass
        if 'M140' in data or 'M190' in data:
            try:
                self.bedTargetTemp = float(
                    re.search('S([0-9]+)', data).group(1))
            except:
                pass

        if 'M105' in data:
            # send simulated temperature data
            self.readList.append("ok T:%.2f /%.2f B:%.2f /%.2f @:64\n" %
                                 (self.temp, self.targetTemp, self.bedTemp, self.bedTargetTemp))
        elif 'M20' in data:
            if self._sdCardReady:
                self._listSd()
        elif 'M21' in data:
            self._sdCardReady = True
            self.readList.append("SD card ok")
        elif 'M22' in data:
            self._sdCardReady = False
        elif 'M23' in data:
            if self._sdCardReady:
                filename = data.split(None, 1)[1].strip()
                self._selectSdFile(filename)
        elif 'M24' in data:
            if self._sdCardReady:
                self._startSdPrint()
        elif 'M25' in data:
            if self._sdCardReady:
                self._pauseSdPrint()
        elif 'M26' in data:
            if self._sdCardReady:
                pos = int(re.search("S([0-9]+)", data).group(1))
                self._setSdPos(pos)
        elif 'M27' in data:
            if self._sdCardReady:
                self._reportSdStatus()
        elif 'M28' in data:
            if self._sdCardReady:
                filename = data.split(None, 1)[1].strip()
                self._writeSdFile(filename)
        elif 'M29' in data:
            if self._sdCardReady:
                self._finishSdFile()
        elif 'M30' in data:
            if self._sdCardReady:
                filename = data.split(None, 1)[1].strip()
                self._deleteSdFile(filename)
        elif "M114" in data:
            # send dummy position report
            self.readList.append("ok C: X:10.00 Y:3.20 Z:5.20 E:1.24")
        elif "M117" in data:
            # we'll just use this to echo a message, to allow playing around
            # with pause triggers
            self.readList.append(
                "ok %s" % re.search("M117\s+(.*)", data).group(1))
        elif "M999" in data:
            # mirror Marlin behaviour
            self.readList.append("Resend: 1")
        elif len(data.strip()) > 0:
            self._sendOk()
예제 #26
0
 def _sendOk(self):
     if settings.get("virtual_printer", "ok_with_line_number"):
         self.readList.append("ok %d" % self.lastN)
     else:
         self.readList.append("ok")
예제 #27
0
def init_pluginsystem(settings, safe_mode=False):
	"""Initializes the plugin manager based on the settings."""

	import os

	logger = log.getLogger(__name__)

	plugin_folders = [(os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), "plugins")), True),
	                  settings.getBaseFolder("plugins")]
	plugin_entry_points = ["octoprint.plugin"]
	plugin_disabled_list = settings.get(["plugins", "_disabled"])

	plugin_validators = []
	if safe_mode:
		def validator(phase, plugin_info):
			if phase == "after_load":
				setattr(plugin_info, "safe_mode_victim", not plugin_info.bundled)
				setattr(plugin_info, "safe_mode_enabled", False)
			elif phase == "before_enable":
				if not plugin_info.bundled:
					setattr(plugin_info, "safe_mode_enabled", True)
					return False
			return True
		plugin_validators.append(validator)

	from octoprint.plugin import plugin_manager
	pm = plugin_manager(init=True,
	                    plugin_folders=plugin_folders,
	                    plugin_entry_points=plugin_entry_points,
	                    plugin_disabled_list=plugin_disabled_list,
	                    plugin_validators=plugin_validators)

	settings_overlays = dict()
	disabled_from_overlays = dict()

	def handle_plugin_loaded(name, plugin):
		if hasattr(plugin.instance, "__plugin_settings_overlay__"):
			plugin.needs_restart = True

			# plugin has a settings overlay, inject it
			overlay_definition = getattr(plugin.instance, "__plugin_settings_overlay__")
			if isinstance(overlay_definition, (tuple, list)):
				overlay_definition, order = overlay_definition
			else:
				order = None

			overlay = settings.load_overlay(overlay_definition)

			if "plugins" in overlay and "_disabled" in overlay["plugins"]:
				disabled_plugins = overlay["plugins"]["_disabled"]
				del overlay["plugins"]["_disabled"]
				disabled_from_overlays[name] = (disabled_plugins, order)

			settings_overlays[name] = overlay
			logger.debug("Found settings overlay on plugin {}".format(name))

	def handle_plugins_loaded(startup=False, initialize_implementations=True, force_reload=None):
		if not startup:
			return

		sorted_disabled_from_overlays = sorted([(key, value[0], value[1]) for key, value in disabled_from_overlays.items()], key=lambda x: (x[2] is None, x[2], x[0]))

		disabled_list = pm.plugin_disabled_list
		already_processed = []
		for name, addons, _ in sorted_disabled_from_overlays:
			if not name in disabled_list and not name.endswith("disabled"):
				for addon in addons:
					if addon in disabled_list:
						continue

					if addon in already_processed:
						logger.info("Plugin {} wants to disable plugin {}, but that was already processed".format(name, addon))

					if not addon in already_processed and not addon in disabled_list:
						disabled_list.append(addon)
						logger.info("Disabling plugin {} as defined by plugin {} through settings overlay".format(addon, name))
				already_processed.append(name)

	def handle_plugin_enabled(name, plugin):
		if name in settings_overlays:
			settings.add_overlay(settings_overlays[name])
			logger.info("Added settings overlay from plugin {}".format(name))

	pm.on_plugin_loaded = handle_plugin_loaded
	pm.on_plugins_loaded = handle_plugins_loaded
	pm.on_plugin_enabled = handle_plugin_enabled
	pm.reload_plugins(startup=True, initialize_implementations=False)
	return pm
예제 #28
0
    def _createMovie(self):
        ffmpeg = settings.get("webcam", "ffmpeg")
        bitrate = settingsng_.get("webcam", "bitrate")
        if ffmpeg is None or bitrate is None:
            self._logger.warn(
                "Cannot create movie, path to ffmpeg or desired bitrate is unset")
            return

        input = os.path.join(self._captureDir, "tmp_%05d.jpg")
        output = os.path.join(self._movieDir, "%s_%s.mpg" % (
            os.path.splitext(self._gcodeFile)[0], time.strftime("%Y%m%d%H%M%S")))

        # prepare ffmpeg command
        command = [
            ffmpeg, '-i', input, '-vcodec', 'mpeg2video', '-pix_fmt', 'yuv420p', '-r', '25', '-y', '-b:v', bitrate,
            '-f', 'vob']

        filters = []

        # flip video if configured
        if settings.get("webcam", "flipH"):
            filters.append('hflip')
        if settings.get("webcam", "flipV"):
            filters.append('vflip')

        # add watermark if configured
        watermarkFilter = None
        if settings.get("webcam", "watermark"):
            watermark = os.path.join(
                os.path.dirname(__file__), "static", "img", "watermark.png")
            if sys.platform == "win32":
                # Because ffmpeg hiccups on windows' drive letters and backslashes we have to give the watermark
                # path a special treatment. Yeah, I couldn't believe it
                # either...
                watermark = watermark.replace("\\", "/").replace(":", "\\\\:")

            watermarkFilter = "movie=%s [wm]; [%%(inputName)s][wm] overlay=10:main_h-overlay_h-10" % watermark

        filterstring = None
        if len(filters) > 0:
            if watermarkFilter is not None:
                filterstring = "[in] %s [postprocessed]; %s [out]" % (
                    ",".join(filters), watermarkFilter % {"inputName": "postprocessed"})
            else:
                filterstring = "[in] %s [out]" % ",".join(filters)
        elif watermarkFilter is not None:
            filterstring = watermarkFilter % {"inputName": "in"} + " [out]"

        if filterstring is not None:
            self._logger.debug("Applying videofilter chain: %s" % filterstring)
            command.extend(["-vf", filterstring])

        # finalize command with output file
        self._logger.debug("Rendering movie to %s" % output)
        command.append(output)
        try:
            subprocess.check_call(command)
            eventManager().fire("MovieDone", output)
        except subprocess.CalledProcessError as (e):
            self._logger.warn(
                "Could not render movie, got return code %r" % e.returncode)
예제 #29
0
def uploadGcodeFile(target):
    if not target in [FileDestinations.LOCAL, FileDestinations.SDCARD]:
        return make_response("Invalid target: %s" % target, 400)

    if "gcode_file" in request.files.keys():
        file = request.files["gcode_file"]
        sd = target == FileDestinations.SDCARD
        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

        # determine current job
        currentFilename = None
        currentSd = None
        currentJob = printer.getCurrentJob()
        if currentJob is not None and "filename" in currentJob.keys() and "sd" in currentJob.keys():
            currentFilename = currentJob["filename"]
            currentSd = currentJob["sd"]

        # determine future filename of file to be uploaded, abort if it can't
        # be uploaded
        futureFilename = gcodeManager.getFutureFilename(file)
        if futureFilename is None or (not settings.get("cura", "enabled") and not gcodefiles.isGcodeFileName(futureFilename)):
            return make_response("Can not upload file %s, wrong format?" % file.filename, 400)

        # prohibit overwriting currently selected file while it's being printed
        if futureFilename == currentFilename and sd == currentSd and printer.isPrinting() or printer.isPaused():
            return make_response("Trying to overwrite file that is currently being printed: %s" % currentFilename, 403)

        filename = None

        def fileProcessingFinished(filename, absFilename, destination):
            """
            Callback for when the file processing (upload, optional slicing, addition to analysis queue) has
            finished.

            Depending on the file's destination triggers either streaming to SD card or directly calls selectOrPrint.
            """
            sd = destination == FileDestinations.SDCARD
            if sd:
                printer.addSdFile(filename, absFilename, selectAndOrPrint)
            else:
                selectAndOrPrint(absFilename, destination)

        def selectAndOrPrint(nameToSelect, destination):
            """
            Callback for when the file is ready to be selected and optionally printed. For SD file uploads this 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.
            """
            sd = destination == FileDestinations.SDCARD
            if selectAfterUpload or printAfterSelect or (currentFilename == filename and currentSd == sd):
                printer.selectFile(nameToSelect, sd, printAfterSelect)

        destination = FileDestinations.SDCARD if sd else FileDestinations.LOCAL
        filename, done = gcodeManager.addFile(
            file, destination, fileProcessingFinished)
        if filename is None:
            return make_response("Could not upload the file %s" % file.filename, 500)

        eventManager.fire("Upload", filename)
        return jsonify(files=gcodeManager.getAllFileData(), filename=filename, done=done)
    else:
        return make_response("No gcode_file included", 400)
예제 #30
0
    def _load(self, gcodeFile):
        filePos = 0
        pos = [0.0, 0.0, 0.0]
        posOffset = [0.0, 0.0, 0.0]
        currentE = 0.0
        totalExtrusion = 0.0
        maxExtrusion = 0.0
        currentExtruder = 0
        totalMoveTimeMinute = 0.0
        absoluteE = True
        scale = 1.0
        posAbs = True
        feedRateXY = settings.get("movement_speed", "x")
        for line in gcodeFile:
            if self._abort:
                raise AnalysisAborted()
            filePos += 1

            try:
                if self.progressCallback is not None and (filePos % 1000 == 0):
                    if isinstance(gcodeFile, (file)):
                        self.progressCallback(
                            float(gcodeFile.tell()) / float(self._fileSize))
                    elif isinstance(gcodeFile, (list)):
                        self.progressCallback(
                            float(filePos) / float(len(gcodeFile)))
            except:
                pass

            if ';' in line:
                comment = line[line.find(';') + 1:].strip()
                if comment.startswith("filament_diameter"):
                    self._filamentDiameter = float(
                        comment.split("=", 1)[1].strip())
                elif comment.startswith("CURA_PROFILE_STRING"):
                    curaOptions = self._parseCuraProfileString(comment)
                    if "filament_diameter" in curaOptions:
                        try:
                            self._filamentDiameter = float(
                                curaOptions["filament_diameter"])
                        except:
                            self._filamentDiameter = 0.0
                line = line[0:line.find(';')]

            T = getCodeInt(line, 'T')
            if T is not None:
                if currentExtruder > 0:
                    posOffset[
                        0] -= getPreference('extruder_offset_x%d' % (currentExtruder), 0.0)
                    posOffset[
                        1] -= getPreference('extruder_offset_y%d' % (currentExtruder), 0.0)
                currentExtruder = T
                if currentExtruder > 0:
                    posOffset[
                        0] += getPreference('extruder_offset_x%d' % (currentExtruder), 0.0)
                    posOffset[
                        1] += getPreference('extruder_offset_y%d' % (currentExtruder), 0.0)

            G = getCodeInt(line, 'G')
            if G is not None:
                if G == 0 or G == 1:  # Move
                    x = getCodeFloat(line, 'X')
                    y = getCodeFloat(line, 'Y')
                    z = getCodeFloat(line, 'Z')
                    e = getCodeFloat(line, 'E')
                    f = getCodeFloat(line, 'F')
                    oldPos = pos
                    pos = pos[:]
                    if posAbs:
                        if x is not None:
                            pos[0] = x * scale + posOffset[0]
                        if y is not None:
                            pos[1] = y * scale + posOffset[1]
                        if z is not None:
                            pos[2] = z * scale + posOffset[2]
                    else:
                        if x is not None:
                            pos[0] += x * scale
                        if y is not None:
                            pos[1] += y * scale
                        if z is not None:
                            pos[2] += z * scale
                    if f is not None:
                        feedRateXY = f
                    if x is not None or y is not None or z is not None:
                        diffX = oldPos[0] - pos[0]
                        diffY = oldPos[1] - pos[1]
                        totalMoveTimeMinute += math.sqrt(
                            diffX * diffX + diffY * diffY) / feedRateXY
                    moveType = 'move'
                    if e is not None:
                        if absoluteE:
                            e -= currentE
                        if e > 0.0:
                            moveType = 'extrude'
                        if e < 0.0:
                            moveType = 'retract'
                        totalExtrusion += e
                        currentE += e
                        if totalExtrusion > maxExtrusion:
                            maxExtrusion = totalExtrusion
                    else:
                        e = 0.0
                    if moveType == 'move' and oldPos[2] != pos[2]:
                        if oldPos[2] > pos[2] and abs(oldPos[2] - pos[2]) > 5.0 and pos[2] < 1.0:
                            oldPos[2] = 0.0
                elif G == 4:  # Delay
                    S = getCodeFloat(line, 'S')
                    if S is not None:
                        totalMoveTimeMinute += S / 60.0
                    P = getCodeFloat(line, 'P')
                    if P is not None:
                        totalMoveTimeMinute += P / 60.0 / 1000.0
                elif G == 20:  # Units are inches
                    scale = 25.4
                elif G == 21:  # Units are mm
                    scale = 1.0
                elif G == 28:  # Home
                    x = getCodeFloat(line, 'X')
                    y = getCodeFloat(line, 'Y')
                    z = getCodeFloat(line, 'Z')
                    center = [0.0, 0.0, 0.0]
                    if x is None and y is None and z is None:
                        pos = center
                    else:
                        pos = pos[:]
                        if x is not None:
                            pos[0] = center[0]
                        if y is not None:
                            pos[1] = center[1]
                        if z is not None:
                            pos[2] = center[2]
                elif G == 90:  # Absolute position
                    posAbs = True
                elif G == 91:  # Relative position
                    posAbs = False
                elif G == 92:
                    x = getCodeFloat(line, 'X')
                    y = getCodeFloat(line, 'Y')
                    z = getCodeFloat(line, 'Z')
                    e = getCodeFloat(line, 'E')
                    if e is not None:
                        currentE = e
                    if x is not None:
                        posOffset[0] = pos[0] - x
                    if y is not None:
                        posOffset[1] = pos[1] - y
                    if z is not None:
                        posOffset[2] = pos[2] - z
            else:
                M = getCodeInt(line, 'M')
                if M is not None:
                    if M == 82:  # Absolute E
                        absoluteE = True
                    elif M == 83:  # Relative E
                        absoluteE = False
        if self.progressCallback is not None:
            self.progressCallback(100.0)
        self.extrusionAmount = maxExtrusion
        self.totalMoveTimeMinute = totalMoveTimeMinute
예제 #31
0
def get_plugin_blacklist(settings, connectivity_checker=None):
	import requests
	import os
	import time
	import yaml

	from octoprint.util import bom_aware_open
	from octoprint.util.version import is_octoprint_compatible

	logger = log.getLogger(__name__ + ".startup")

	if connectivity_checker is not None and not connectivity_checker.online:
		logger.info("We don't appear to be online, not fetching plugin blacklist")
		return []

	def format_blacklist(entries):
		format_entry = lambda x: "{} ({})".format(x[0], x[1]) if isinstance(x, (list, tuple)) and len(x) == 2 \
			else "{} (any)".format(x)
		return ", ".join(map(format_entry, entries))

	def process_blacklist(entries):
		result = []

		if not isinstance(entries, list):
			return result

		for entry in entries:
			if not "plugin" in entry:
				continue

			if "octoversions" in entry and not is_octoprint_compatible(*entry["octoversions"]):
				continue

			if "version" in entry:
				logger.debug("Blacklisted plugin: {}, version: {}".format(entry["plugin"], entry["version"]))
				result.append((entry["plugin"], entry["version"]))
			elif "versions" in entry:
				logger.debug("Blacklisted plugin: {}, versions: {}".format(entry["plugin"], ", ".join(entry["versions"])))
				for version in entry["versions"]:
					result.append((entry["plugin"], version))
			else:
				logger.debug("Blacklisted plugin: {}".format(entry["plugin"]))
				result.append(entry["plugin"])

		return result

	def fetch_blacklist_from_cache(path, ttl):
		if not os.path.isfile(path):
			return None

		if os.stat(path).st_mtime + ttl < time.time():
			return None

		with bom_aware_open(path, encoding="utf-8", mode="r") as f:
			result = yaml.safe_load(f)

		if isinstance(result, list):
			return result

	def fetch_blacklist_from_url(url, timeout=3, cache=None):
		result = []
		try:
			r = requests.get(url, timeout=timeout)
			result = process_blacklist(r.json())

			if cache is not None:
				try:
					with bom_aware_open(cache, encoding="utf-8", mode="w") as f:
						yaml.safe_dump(result, f)
				except:
					logger.info("Fetched plugin blacklist but couldn't write it to its cache file.")
		except:
			logger.info("Unable to fetch plugin blacklist from {}, proceeding without it.".format(url))
		return result

	try:
		# first attempt to fetch from cache
		cache_path = os.path.join(settings.getBaseFolder("data"), "plugin_blacklist.yaml")
		ttl = settings.getInt(["server", "pluginBlacklist", "ttl"])
		blacklist = fetch_blacklist_from_cache(cache_path, ttl)

		if blacklist is None:
			# no result from the cache, let's fetch it fresh
			url = settings.get(["server", "pluginBlacklist", "url"])
			timeout = settings.getFloat(["server", "pluginBlacklist", "timeout"])
			blacklist = fetch_blacklist_from_url(url, timeout=timeout, cache=cache_path)

		if blacklist is None:
			# still now result, so no blacklist
			blacklist = []

		if blacklist:
			logger.info("Blacklist processing done, "
			            "adding {} blacklisted plugin versions: {}".format(len(blacklist),
			                                                               format_blacklist(blacklist)))
		else:
			logger.info("Blacklist processing done")

		return blacklist
	except:
		logger.exception("Something went wrong while processing the plugin blacklist. Proceeding without it.")
예제 #32
0
파일: util.py 프로젝트: d42/octoprint-fork
 def decorated_view(*args, **kwargs):
     if settings.get("server", "first_run") and (userManager is None or not userManager.hasBeenCustomized()):
         return make_response("OctoPrint isn't setup yet", 403)
     return login_required(func)(*args, **kwargs)
예제 #33
0
    def run(self):
        if not self._allowRoot:
            self._checkForRoot()
        global gcodeManager
        global userManager
        global eventManager
        global loginManager
        global debug

        from tornado.wsgi import WSGIContainer
        from tornado.httpserver import HTTPServer
        from tornado.ioloop import IOLoop
        from tornado.web import Application, FallbackHandler

        debug = self._debug

        # then initialize logging
        self._initLogging(self._debug)
        logger = logging.getLogger(__name__)

        eventManager = events.eventManager()
        gcodeManager = gcodefiles.GcodeManager()
        self.printer = Printer(gcodeManager)

        # configure timelapse
        octoprint.timelapse.configureTimelapse()

        # setup system and gcode command triggers
        events.SystemCommandTrigger(self.printer)
        events.GcodeCommandTrigger(self.printer)
        if self._debug:
            events.DebugEventListener()

        if settings.get("access_control", "enabled"):
            userManagerName = settings.get("access_control", "user_manager")
            try:
                clazz = util.getClass(userManagerName)
                userManager = clazz()
            except AttributeError as e:
                logger.exception(
                    "Could not instantiate user manager %s, will run with accessControl disabled!" % userManagerName)

        app.wsgi_app = ReverseProxied(app.wsgi_app)

        app.secret_key = settings.get('server', 'secret_key')
        if not app.secret_key:
            raise NoSecretKeyError()
        loginManager = LoginManager()
        loginManager.session_protection = "strong"
        loginManager.user_callback = load_user
        if userManager is None:
            loginManager.anonymous_user = users.DummyUser
            principals.identity_loaders.appendleft(users.dummy_identity_loader)
        loginManager.init_app(app)

        if self._host is None:
            self._host = settings.get("server", "host")
        if self._port is None:
            self._port = settings.get("server", "port")

        logger.info("Listening on http://%s:%d" % (self._host, self._port))
        app.debug = self._debug

        from octoprint.server.ajax import ajax
        from octoprint.server.api import api

        app.register_blueprint(ajax, url_prefix="/ajax")
        app.register_blueprint(api, url_prefix="/api")

        self._router = SockJSRouter(self._createSocketConnection, "/sockjs")

        self._tornado_app = Application(self._router.urls + [
            (r"/downloads/timelapse/([^/]*\.mpg)", LargeResponseHandler, {
             "path": settings.getpath("timelapse"), "as_attachment": True}),
            (r"/downloads/gcode/([^/]*\.(gco|gcode))", LargeResponseHandler, {
                "path": settings.getpath("uploads"), "as_attachment": True}),
            (r".*", FallbackHandler,
             {"fallback": WSGIContainer(app.wsgi_app)})
        ])
        self._server = HTTPServer(self._tornado_app)
        self._server.listen(self._port, address=self._host)

        eventManager.fire("Startup")
        if settings.get("serial", "autoconnect"):
            port, baudrate = (settings.get('serial', e) 
                              for e in ('port', 'baudrate'))
            connectionOptions = getConnectionOptions()
            if port in connectionOptions["ports"]:
                self.printer.connect(port, baudrate)
        try:
            IOLoop.instance().start()
        except:
            logger.fatal(
                "Now that is embarrassing... Something really really went"
                "wrong here. Please report this including the stacktrace below"
                "in OctoPrint's bugtracker. Thanks!")
            logger.exception("Stacktrace follows:")