MrDraw/src/octoprint/server/util/sockjs.py
Gina Häußge 8ff0096eb6 Fix & Docs: Plugins may only have one mixin implementation
Multiple mixins are allowed of course. Allowing multiple implementations lead to too many problems due to plugin names for referring to the APIs of SimpleApiPlugins or the assets of AssetPlugins.

 Hence __plugin_implementations__ has been deprecated in favor of __plugin_implementation__. The plugin subsystem will automatically copy the first implementation from __plugin_implementations__ to __plugin_implementation__ and log a deprecation warning.

 Adjusted documentation accordingly. Also added docs for helpers.
2015-03-30 16:50:06 +02:00

144 lines
5.1 KiB
Python

# coding=utf-8
from __future__ import absolute_import
__author__ = "Gina Häußge <osd@foosel.net>"
__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
__copyright__ = "Copyright (C) 2014 The OctoPrint Project - Released under terms of the AGPLv3 License"
import logging
import threading
import sockjs.tornado
import octoprint.timelapse
import octoprint.server
from octoprint.events import Events
import octoprint.printer
class PrinterStateConnection(sockjs.tornado.SockJSConnection, octoprint.printer.PrinterCallback):
def __init__(self, printer, fileManager, analysisQueue, userManager, eventManager, pluginManager, session):
sockjs.tornado.SockJSConnection.__init__(self, session)
self._logger = logging.getLogger(__name__)
self._temperatureBacklog = []
self._temperatureBacklogMutex = threading.Lock()
self._logBacklog = []
self._logBacklogMutex = threading.Lock()
self._messageBacklog = []
self._messageBacklogMutex = threading.Lock()
self._printer = printer
self._fileManager = fileManager
self._analysisQueue = analysisQueue
self._userManager = userManager
self._eventManager = eventManager
self._pluginManager = pluginManager
self._remoteAddress = None
def _getRemoteAddress(self, info):
forwardedFor = info.headers.get("X-Forwarded-For")
if forwardedFor is not None:
return forwardedFor.split(",")[0]
return info.ip
def on_open(self, info):
self._remoteAddress = self._getRemoteAddress(info)
self._logger.info("New connection from client: %s" % self._remoteAddress)
# connected => update the API key, might be necessary if the client was left open while the server restarted
self._emit("connected", {"apikey": octoprint.server.UI_API_KEY, "version": octoprint.server.VERSION, "display_version": octoprint.server.DISPLAY_VERSION})
self._printer.register_callback(self)
self._fileManager.register_slicingprogress_callback(self)
octoprint.timelapse.registerCallback(self)
self._pluginManager.register_message_receiver(self.on_plugin_message)
self._eventManager.fire(Events.CLIENT_OPENED, {"remoteAddress": self._remoteAddress})
for event in octoprint.events.all_events():
self._eventManager.subscribe(event, self._onEvent)
octoprint.timelapse.notifyCallbacks(octoprint.timelapse.current)
def on_close(self):
self._logger.info("Client connection closed: %s" % self._remoteAddress)
self._printer.unregister_callback(self)
self._fileManager.unregister_slicingprogress_callback(self)
octoprint.timelapse.unregisterCallback(self)
self._pluginManager.unregister_message_receiver(self.on_plugin_message)
self._eventManager.fire(Events.CLIENT_CLOSED, {"remoteAddress": self._remoteAddress})
for event in octoprint.events.all_events():
self._eventManager.unsubscribe(event, self._onEvent)
def on_message(self, message):
pass
def on_printer_send_current_data(self, data):
# add current temperature, log and message backlogs to sent data
with self._temperatureBacklogMutex:
temperatures = self._temperatureBacklog
self._temperatureBacklog = []
with self._logBacklogMutex:
logs = self._logBacklog
self._logBacklog = []
with self._messageBacklogMutex:
messages = self._messageBacklog
self._messageBacklog = []
busy_files = [dict(origin=v[0], name=v[1]) for v in self._fileManager.get_busy_files()]
if "job" in data and data["job"] is not None \
and "file" in data["job"] and "name" in data["job"]["file"] and "origin" in data["job"]["file"] \
and data["job"]["file"]["name"] is not None and data["job"]["file"]["origin"] is not None \
and (self._printer.is_printing() or self._printer.is_paused()):
busy_files.append(dict(origin=data["job"]["file"]["origin"], name=data["job"]["file"]["name"]))
data.update({
"temps": temperatures,
"logs": logs,
"messages": messages,
"busyFiles": busy_files,
})
self._emit("current", data)
def on_printer_send_initial_data(self, data):
self._emit("history", data)
def sendEvent(self, type, payload=None):
self._emit("event", {"type": type, "payload": payload})
def sendTimelapseConfig(self, timelapseConfig):
self._emit("timelapse", timelapseConfig)
def sendSlicingProgress(self, slicer, source_location, source_path, dest_location, dest_path, progress):
self._emit("slicingProgress",
dict(slicer=slicer, source_location=source_location, source_path=source_path, dest_location=dest_location, dest_path=dest_path, progress=progress)
)
def on_plugin_message(self, plugin, data):
self._emit("plugin", dict(plugin=plugin, data=data))
def on_printer_add_log(self, data):
with self._logBacklogMutex:
self._logBacklog.append(data)
def on_printer_add_message(self, data):
with self._messageBacklogMutex:
self._messageBacklog.append(data)
def on_printer_add_temperature(self, data):
with self._temperatureBacklogMutex:
self._temperatureBacklog.append(data)
def _onEvent(self, event, payload):
self.sendEvent(event, payload)
def _emit(self, type, payload):
try:
self.send({type: payload})
except Exception as e:
self._logger.warn("Could not send message to client %s: %s" % (self._remoteAddress, str(e)))