Finalized decoupling of timelapse from printer module, made sure timelapse is properly unregistered from eventbus on change

master
Gina Häußge 2013-06-16 22:42:18 +02:00
parent 236e26979f
commit 0e56952913
3 changed files with 57 additions and 37 deletions

View File

@ -73,9 +73,6 @@ class Printer():
self._selectedFile = None self._selectedFile = None
# timelapse
self._timelapse = None
# comm # comm
self._comm = None self._comm = None
@ -215,15 +212,6 @@ class Printer():
self._gcodeManager.printFailed(self._selectedFile["filename"]) self._gcodeManager.printFailed(self._selectedFile["filename"])
eventManager().fire("PrintFailed", self._filename) eventManager().fire("PrintFailed", self._filename)
def setTimelapse(self, timelapse):
if self._timelapse is not None and self.isPrinting():
self._timelapse.stopTimelapse()
del self._timelapse
self._timelapse = timelapse
def getTimelapse(self):
return self._timelapse
#~~ state monitoring #~~ state monitoring
def _setCurrentZ(self, currentZ): def _setCurrentZ(self, currentZ):

View File

@ -15,7 +15,7 @@ import subprocess
from octoprint.printer import Printer, getConnectionOptions from octoprint.printer import Printer, getConnectionOptions
from octoprint.settings import settings, valid_boolean_trues from octoprint.settings import settings, valid_boolean_trues
import octoprint.timelapse as timelapse import octoprint.timelapse
import octoprint.gcodefiles as gcodefiles import octoprint.gcodefiles as gcodefiles
import octoprint.util as util import octoprint.util as util
import octoprint.users as users import octoprint.users as users
@ -28,7 +28,9 @@ BASEURL = "/ajax/"
app = Flask("octoprint") app = Flask("octoprint")
# Only instantiated by the Server().run() method # Only instantiated by the Server().run() method
# In order that threads don't start too early when running as a Daemon # In order that threads don't start too early when running as a Daemon
printer = None printer = None
timelapse = None
gcodeManager = None gcodeManager = None
userManager = None userManager = None
eventManager = None eventManager = None
@ -60,8 +62,8 @@ class PrinterStateConnection(tornadio2.SocketConnection):
def on_open(self, info): def on_open(self, info):
self._logger.info("New connection from client") self._logger.info("New connection from client")
# Use of global here is smelly # Use of global here is smelly
printer.registerCallback(self) self._printer.registerCallback(self)
gcodeManager.registerCallback(self) self._gcodeManager.registerCallback(self)
self._eventManager.fire("ClientOpened") self._eventManager.fire("ClientOpened")
self._eventManager.subscribe("MovieDone", self._onMovieDone) self._eventManager.subscribe("MovieDone", self._onMovieDone)
@ -69,8 +71,8 @@ class PrinterStateConnection(tornadio2.SocketConnection):
def on_close(self): def on_close(self):
self._logger.info("Closed client connection") self._logger.info("Closed client connection")
# Use of global here is smelly # Use of global here is smelly
printer.unregisterCallback(self) self._printer.unregisterCallback(self)
gcodeManager.unregisterCallback(self) self._gcodeManager.unregisterCallback(self)
self._eventManager.fire("ClientClosed") self._eventManager.fire("ClientClosed")
self._eventManager.unsubscribe("MovieDone", self._onMovieDone) self._eventManager.unsubscribe("MovieDone", self._onMovieDone)
@ -352,19 +354,19 @@ def refreshFiles():
@app.route(BASEURL + "timelapse", methods=["GET"]) @app.route(BASEURL + "timelapse", methods=["GET"])
def getTimelapseData(): def getTimelapseData():
lapse = printer.getTimelapse() global timelapse
type = "off" type = "off"
additionalConfig = {} additionalConfig = {}
if lapse is not None and isinstance(lapse, timelapse.ZTimelapse): if timelapse is not None and isinstance(timelapse, octoprint.timelapse.ZTimelapse):
type = "zchange" type = "zchange"
elif lapse is not None and isinstance(lapse, timelapse.TimedTimelapse): elif timelapse is not None and isinstance(timelapse, octoprint.timelapse.TimedTimelapse):
type = "timed" type = "timed"
additionalConfig = { additionalConfig = {
"interval": lapse.interval() "interval": timelapse.interval()
} }
files = timelapse.getFinishedTimelapses() files = octoprint.timelapse.getFinishedTimelapses()
for file in files: for file in files:
file["url"] = url_for("downloadTimelapse", filename=file["name"]) file["url"] = url_for("downloadTimelapse", filename=file["name"])
@ -391,11 +393,17 @@ def deleteTimelapse(filename):
@app.route(BASEURL + "timelapse", methods=["POST"]) @app.route(BASEURL + "timelapse", methods=["POST"])
@login_required @login_required
def setTimelapseConfig(): def setTimelapseConfig():
global timelapse
if request.values.has_key("type"): if request.values.has_key("type"):
type = request.values["type"] type = request.values["type"]
lapse = None if type in ["zchange", "timed"]:
# valid timelapse type, check if there is an old one we need to stop first
if timelapse is not None:
timelapse.unload()
timelapse = None
if "zchange" == type: if "zchange" == type:
lapse = timelapse.ZTimelapse() timelapse = octoprint.timelapse.ZTimelapse()
elif "timed" == type: elif "timed" == type:
interval = 10 interval = 10
if request.values.has_key("interval"): if request.values.has_key("interval"):
@ -403,8 +411,7 @@ def setTimelapseConfig():
interval = int(request.values["interval"]) interval = int(request.values["interval"])
except ValueError: except ValueError:
pass pass
lapse = timelapse.TimedTimelapse(interval) timelapse = octoprint.timelapse.TimedTimelapse(interval)
printer.setTimelapse(lapse)
return getTimelapseData() return getTimelapseData()
@ -802,6 +809,12 @@ class Server():
} }
}, },
"loggers": { "loggers": {
#"octoprint.timelapse": {
# "level": "DEBUG"
#},
#"octoprint.events": {
# "level": "DEBUG"
#}
}, },
"root": { "root": {
"level": "INFO", "level": "INFO",

View File

@ -47,10 +47,23 @@ class Timelapse(object):
self._renderThread = None self._renderThread = None
self._captureMutex = threading.Lock() self._captureMutex = threading.Lock()
# subscribe events
eventManager().subscribe("PrintStarted", self.onPrintStarted) eventManager().subscribe("PrintStarted", self.onPrintStarted)
eventManager().subscribe("PrintFailed", self.onPrintDone) eventManager().subscribe("PrintFailed", self.onPrintDone)
eventManager().subscribe("PrintDone", self.onPrintDone) eventManager().subscribe("PrintDone", self.onPrintDone)
self.subscribeToEvents() for (event, callback) in self.eventSubscriptions():
eventManager().subscribe(event, callback)
def unload(self):
if self._inTimelapse:
self.stopTimelapse(doCreateMovie=False)
# unsubscribe events
eventManager().unsubscribe("PrintStarted", self.onPrintStarted)
eventManager().unsubscribe("PrintFailed", self.onPrintDone)
eventManager().unsubscribe("PrintDone", self.onPrintDone)
for (event, callback) in self.eventSubscriptions():
eventManager().unsubscribe(event, callback)
def onPrintStarted(self, event, payload): def onPrintStarted(self, event, payload):
""" """
@ -64,14 +77,16 @@ class Timelapse(object):
""" """
self.stopTimelapse() self.stopTimelapse()
def subscribeToEvents(self): def eventSubscriptions(self):
""" """
Override this method to subscribe to additional events. Events that are already subscribed: Override this method to subscribe to additional events by returning an array of (event, callback) tuples.
Events that are already subscribed:
* PrintStarted - self.onPrintStarted * PrintStarted - self.onPrintStarted
* PrintFailed - self.onPrintDone * PrintFailed - self.onPrintDone
* PrintDone - self.onPrintDone * PrintDone - self.onPrintDone
""" """
pass return []
def startTimelapse(self, gcodeFile): def startTimelapse(self, gcodeFile):
self._logger.debug("Starting timelapse for %s" % gcodeFile) self._logger.debug("Starting timelapse for %s" % gcodeFile)
@ -81,11 +96,13 @@ class Timelapse(object):
self._inTimelapse = True self._inTimelapse = True
self._gcodeFile = os.path.basename(gcodeFile) self._gcodeFile = os.path.basename(gcodeFile)
def stopTimelapse(self): def stopTimelapse(self, doCreateMovie=True):
self._logger.debug("Stopping timelapse") self._logger.debug("Stopping timelapse")
self._renderThread = threading.Thread(target=self._createMovie)
self._renderThread.daemon = True if doCreateMovie:
self._renderThread.start() self._renderThread = threading.Thread(target=self._createMovie)
self._renderThread.daemon = True
self._renderThread.start()
self._imageNumber = None self._imageNumber = None
self._inTimelapse = False self._inTimelapse = False
@ -157,8 +174,10 @@ class ZTimelapse(Timelapse):
Timelapse.__init__(self) Timelapse.__init__(self)
self._logger.debug("ZTimelapse initialized") self._logger.debug("ZTimelapse initialized")
def subscribeToEvents(self): def eventSubscriptions(self):
eventManager().subscribe("ZChange", self._onZChange) return [
("ZChange", self._onZChange)
]
def _onZChange(self, event, payload): def _onZChange(self, event, payload):
self.captureImage() self.captureImage()