From 8bfa3ef2501242df7d2639a68c0a52c9325c8515 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Fri, 30 Jan 2015 22:22:39 +0100 Subject: [PATCH] Adjusted discovery plugin to new blueprint and settings functionality for plugins --- src/octoprint/plugins/discovery/__init__.py | 202 ++++++++---------- ...{discovery.jinja2 => discovery.xml.jinja2} | 0 2 files changed, 95 insertions(+), 107 deletions(-) rename src/octoprint/plugins/discovery/templates/{discovery.jinja2 => discovery.xml.jinja2} (100%) diff --git a/src/octoprint/plugins/discovery/__init__.py b/src/octoprint/plugins/discovery/__init__.py index 82b6b319..5a7e1dd6 100644 --- a/src/octoprint/plugins/discovery/__init__.py +++ b/src/octoprint/plugins/discovery/__init__.py @@ -50,93 +50,16 @@ def __plugin_init__(): zeroconf_unregister=discovery_plugin.zeroconf_unregister )) - -default_settings = { - "publicHost": None, - "publicPort": None, - "pathPrefix": None, - "httpUsername": None, - "httpPassword": None, - "upnpUuid": None, - "zeroConf": [], - "model": { - "name": None, - "description": None, - "number": None, - "url": None, - "serial": None, - "vendor": None, - "vendorUrl": None - } -} -s = octoprint.plugin.plugin_settings("discovery", defaults=default_settings) - -def get_uuid(): - upnpUuid = s.get(["upnpUuid"]) - if upnpUuid is None: - import uuid - upnpUuid = str(uuid.uuid4()) - s.set(["upnpUuid"], upnpUuid) - s.save() - return upnpUuid -UUID = get_uuid() -del get_uuid - - -def get_instance_name(): - name = s.globalGet(["appearance", "name"]) - if name: - return u"OctoPrint instance \"{}\"".format(name) - else: - import socket - return u"OctoPrint instance on {}".format(socket.gethostname()) - - -#~~ custom blueprint for providing discovery.xml - -blueprint = flask.Blueprint("plugin.discovery", __name__, template_folder=os.path.join(os.path.dirname(os.path.realpath(__file__)), "templates")) - -@blueprint.route("/discovery.xml") -def discovery(): - logging.getLogger("octoprint.plugins." + __name__).debug("Rendering discovery.xml") - - modelName = s.get(["model", "name"]) - if not modelName: - import octoprint.server - modelName = octoprint.server.DISPLAY_VERSION - - vendor = s.get(["model", "vendor"]) - vendorUrl = s.get(["model", "vendorUrl"]) - if not vendor: - vendor = "The OctoPrint Project" - vendorUrl = "http://www.octoprint.org/" - - response = flask.make_response(flask.render_template("discovery.jinja2", - friendlyName=get_instance_name(), - manufacturer=vendor, - manufacturerUrl=vendorUrl, - modelName=modelName, - modelDescription=s.get(["model", "description"]), - modelNumber=s.get(["model", "number"]), - modelUrl=s.get(["model", "url"]), - serialNumber=s.get(["model", "serial"]), - uuid=UUID, - presentationUrl=flask.url_for("index", _external=True))) - response.headers['Content-Type'] = 'application/xml' - return response - - class DiscoveryPlugin(octoprint.plugin.StartupPlugin, octoprint.plugin.ShutdownPlugin, - octoprint.plugin.BlueprintPlugin): + octoprint.plugin.BlueprintPlugin, + octoprint.plugin.SettingsPlugin): ssdp_multicast_addr = "239.255.255.250" ssdp_multicast_port = 1900 def __init__(self): - self.logger = logging.getLogger("octoprint.plugins." + __name__) - self.host = None self.port = None @@ -150,10 +73,58 @@ class DiscoveryPlugin(octoprint.plugin.StartupPlugin, self._ssdp_notify_timeout = 10 self._ssdp_last_notify = 0 + ##~~ SettingsPlugin API + + def get_settings_defaults(self): + return { + "publicHost": None, + "publicPort": None, + "pathPrefix": None, + "httpUsername": None, + "httpPassword": None, + "upnpUuid": None, + "zeroConf": [], + "model": { + "name": None, + "description": None, + "number": None, + "url": None, + "serial": None, + "vendor": None, + "vendorUrl": None + } + } + ##~~ BlueprintPlugin API -- used for providing the SSDP device descriptor XML - def get_blueprint(self): - return blueprint + @octoprint.plugin.BlueprintPlugin.route("/discovery.xml", methods=["GET"]) + def discovery(self): + self._logger.debug("Rendering discovery.xml") + + modelName = self._settings.get(["model", "name"]) + if not modelName: + import octoprint.server + modelName = octoprint.server.DISPLAY_VERSION + + vendor = self._settings.get(["model", "vendor"]) + vendorUrl = self._settings.get(["model", "vendorUrl"]) + if not vendor: + vendor = "The OctoPrint Project" + vendorUrl = "http://www.octoprint.org/" + + response = flask.make_response(flask.render_template("discovery.xml.jinja2", + friendlyName=self.get_instance_name(), + manufacturer=vendor, + manufacturerUrl=vendorUrl, + modelName=modelName, + modelDescription=self._settings.get(["model", "description"]), + modelNumber=self._settings.get(["model", "number"]), + modelUrl=self._settings.get(["model", "url"]), + serialNumber=self._settings.get(["model", "serial"]), + uuid=self.get_uuid(), + presentationUrl=flask.url_for("index", _external=True))) + response.headers['Content-Type'] = 'application/xml' + return response def is_blueprint_protected(self): return False @@ -161,10 +132,10 @@ class DiscoveryPlugin(octoprint.plugin.StartupPlugin, ##~~ StartupPlugin API -- used for registering OctoPrint's Zeroconf and SSDP services upon application startup def on_startup(self, host, port): - public_host = s.get(["publicHost"]) + public_host = self._settings.get(["publicHost"]) if public_host: host = public_host - public_port = s.get(["publicPort"]) + public_port = self._settings.get(["publicPort"]) if public_port: port = public_port @@ -172,13 +143,13 @@ class DiscoveryPlugin(octoprint.plugin.StartupPlugin, self.port = port # Zeroconf - self.zeroconf_register("_http._tcp", get_instance_name(), txt_record=self._create_http_txt_record_dict()) - self.zeroconf_register("_octoprint._tcp", get_instance_name(), txt_record=self._create_octoprint_txt_record_dict()) - for zeroconf in s.get(["zeroConf"]): + self.zeroconf_register("_http._tcp", self.get_instance_name(), txt_record=self._create_http_txt_record_dict()) + self.zeroconf_register("_octoprint._tcp", self.get_instance_name(), txt_record=self._create_octoprint_txt_record_dict()) + for zeroconf in self._settings.get(["zeroConf"]): if "service" in zeroconf: self.zeroconf_register( zeroconf["service"], - zeroconf["name"] if "name" in zeroconf else get_instance_name(), + zeroconf["name"] if "name" in zeroconf else self.get_instance_name(), port=zeroconf["port"] if "port" in zeroconf else None, txt_record=zeroconf["txtRecord"] if "txtRecord" in zeroconf else None ) @@ -213,7 +184,7 @@ class DiscoveryPlugin(octoprint.plugin.StartupPlugin, return if not name: - name = get_instance_name() + name = self.get_instance_name() if not port: port = self.port @@ -227,7 +198,7 @@ class DiscoveryPlugin(octoprint.plugin.StartupPlugin, key = (reg_type, port) self._sd_refs[key] = pybonjour.DNSServiceRegister(**params) - self.logger.info(u"Registered {name} for {reg_type}".format(**locals())) + self._logger.info(u"Registered {name} for {reg_type}".format(**locals())) def zeroconf_unregister(self, reg_type, port=None): """ @@ -251,9 +222,9 @@ class DiscoveryPlugin(octoprint.plugin.StartupPlugin, sd_ref = self._sd_refs[key] try: sd_ref.close() - self.logger.debug("Unregistered {reg_type} on port {port}".format(reg_type=reg_type, port=port)) + self._logger.debug("Unregistered {reg_type} on port {port}".format(reg_type=reg_type, port=port)) except: - self.logger.exception("Could not unregister {reg_type} on port {port}".format(reg_type=reg_type, port=port)) + self._logger.exception("Could not unregister {reg_type} on port {port}".format(reg_type=reg_type, port=port)) def zeroconf_browse(self, service_type, block=True, callback=None, browse_timeout=5, resolve_timeout=5): """ @@ -317,7 +288,7 @@ class DiscoveryPlugin(octoprint.plugin.StartupPlugin, name = fullname[:fullname.find(service_type) - 1].replace("\\032", " ") host = hosttarget[:-1] - self.logger.debug("Resolved a result for Zeroconf resolution of {service_type}: {name} @ {host}".format(service_type=service_type, name=name, host=host)) + self._logger.debug("Resolved a result for Zeroconf resolution of {service_type}: {name} @ {host}".format(service_type=service_type, name=name, host=host)) result.append(dict( name=name, host=host, @@ -333,7 +304,7 @@ class DiscoveryPlugin(octoprint.plugin.StartupPlugin, if not (flags & pybonjour.kDNSServiceFlagsAdd): return - self.logger.debug("Got a browsing result for Zeroconf resolution of {service_type}, resolving...".format(service_type=service_type)) + self._logger.debug("Got a browsing result for Zeroconf resolution of {service_type}, resolving...".format(service_type=service_type)) resolve_ref = pybonjour.DNSServiceResolve(0, interface_index, service_name, regtype, reply_domain, resolve_callback) try: @@ -348,7 +319,7 @@ class DiscoveryPlugin(octoprint.plugin.StartupPlugin, finally: resolve_ref.close() - self.logger.debug("Browsing Zeroconf for {service_type}".format(service_type=service_type)) + self._logger.debug("Browsing Zeroconf for {service_type}".format(service_type=service_type)) def browse(): sd_ref = pybonjour.DNSServiceBrowse(regtype=service_type, callBack=browse_callback) @@ -493,16 +464,16 @@ class DiscoveryPlugin(octoprint.plugin.StartupPlugin, # determine path entry path = "/" - if s.get(["pathPrefix"]): - path = s.get(["pathPrefix"]) + if self._settings.get(["pathPrefix"]): + path = self._settings.get(["pathPrefix"]) else: - prefix = s.globalGet(["server", "reverseProxy", "prefixFallback"]) + prefix = self._settings.globalGet(["server", "reverseProxy", "prefixFallback"]) if prefix: path = prefix # fetch username and password (if set) - username = s.get(["httpUsername"]) - password = s.get(["httpPassword"]) + username = self._settings.get(["httpUsername"]) + password = self._settings.get(["httpPassword"]) entries = dict( path=path @@ -540,10 +511,10 @@ class DiscoveryPlugin(octoprint.plugin.StartupPlugin, api=octoprint.server.api.VERSION, )) - modelName = s.get(["model", "name"]) + modelName = self._settings.get(["model", "name"]) if modelName: entries.update(dict(model=modelName)) - vendor = s.get(["model", "vendor"]) + vendor = self._settings.get(["model", "vendor"]) if vendor: entries.update(dict(vendor=vendor)) @@ -601,7 +572,7 @@ class DiscoveryPlugin(octoprint.plugin.StartupPlugin, location = "http://{addr}:{port}/plugin/discovery/discovery.xml".format(addr=addr, port=self.port) - self.logger.debug("Sending NOTIFY {} via {}".format("alive" if alive else "byebye", addr)) + self._logger.debug("Sending NOTIFY {} via {}".format("alive" if alive else "byebye", addr)) notify_message = "".join([ "NOTIFY * HTTP/1.1\r\n", "Server: Python/2.7\r\n", @@ -612,7 +583,7 @@ class DiscoveryPlugin(octoprint.plugin.StartupPlugin, "USN: uuid:{uuid}::upnp:rootdevice\r\n", "HOST: {mcast_addr}:{mcast_port}\r\n\r\n" ]) - message = notify_message.format(uuid=UUID, + message = notify_message.format(uuid=self.get_uuid(), location=location, nts="ssdp:alive" if alive else "ssdp:byebye", mcast_addr=self.__class__.ssdp_multicast_addr, @@ -666,7 +637,7 @@ class DiscoveryPlugin(octoprint.plugin.StartupPlugin, sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(self.__class__.ssdp_multicast_addr) + socket.inet_aton('0.0.0.0')) - self.logger.info(u"Registered {} for SSDP".format(get_instance_name())) + self._logger.info(u"Registered {} for SSDP".format(self.get_instance_name())) self._ssdp_notify(alive=True) @@ -678,11 +649,11 @@ class DiscoveryPlugin(octoprint.plugin.StartupPlugin, if not request.error_code and request.command == "M-SEARCH" and request.path == "*" and (request.headers["ST"] == "upnp:rootdevice" or request.headers["ST"] == "ssdp:all") and request.headers["MAN"] == '"ssdp:discover"': interface_address = octoprint.util.address_for_client(*address) if not interface_address: - self.logger.warn("Can't determine address to user for client {}, not sending a M-SEARCH reply".format(address)) + self._logger.warn("Can't determine address to user for client {}, not sending a M-SEARCH reply".format(address)) continue - message = location_message.format(uuid=UUID, location="http://{host}:{port}/plugin/discovery/discovery.xml".format(host=interface_address, port=self.port)) + message = location_message.format(uuid=self.get_uuid(), location="http://{host}:{port}/plugin/discovery/discovery.xml".format(host=interface_address, port=self.port)) sock.sendto(message, address) - self.logger.debug("Sent M-SEARCH reply for {path} and {st} to {address!r}".format(path=request.path, st=request.headers["ST"], address=address)) + self._logger.debug("Sent M-SEARCH reply for {path} and {st} to {address!r}".format(path=request.path, st=request.headers["ST"], address=address)) except socket.timeout: pass finally: @@ -693,4 +664,21 @@ class DiscoveryPlugin(octoprint.plugin.StartupPlugin, except: pass + ##~~ helpers + def get_uuid(self): + upnpUuid = self._settings.get(["upnpUuid"]) + if upnpUuid is None: + import uuid + upnpUuid = str(uuid.uuid4()) + self._settings.set(["upnpUuid"], upnpUuid) + self._settings.save() + return upnpUuid + + def get_instance_name(self): + name = self._settings.globalGet(["appearance", "name"]) + if name: + return u"OctoPrint instance \"{}\"".format(name) + else: + import socket + return u"OctoPrint instance on {}".format(socket.gethostname()) diff --git a/src/octoprint/plugins/discovery/templates/discovery.jinja2 b/src/octoprint/plugins/discovery/templates/discovery.xml.jinja2 similarity index 100% rename from src/octoprint/plugins/discovery/templates/discovery.jinja2 rename to src/octoprint/plugins/discovery/templates/discovery.xml.jinja2