API event "PrintDone" not firing - bug, or am I doing something wrong?

What is the problem?
I'm trying to hook on to the "PrintDone" event the following way;

	def on_event(self, event, payload):
		server_ip = [(s.connect((self._settings.global_get(["server","onlineCheck","host"]), self._settings.global_get(["server","onlineCheck","port"]))), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]
		
		if event == "PrinterStateChanged":
			webresponse = urllib2.urlopen("the_url&printer_state=" + payload["state_string"]).read()
			self._logger.info("Told server about printer state changed, response: " + webresponse)
		if event == "PrintDone":
			theUrl = "url"
			webresponse = urllib2.urlopen(theUrl)
			self._logger.info("Told server that the print is finished, response: " + webresponse)
		if event == "PrintFailed":
			theUrl = "url"
			webresponse = urllib2.urlopen(theUrl)
			self._logger.info("Told server that the print has failed, response: " + webresponse)
			
		self._logger.info("KMG - EVENT NAME: " + event)

PrinterStateChanged is fired and works perfectly, however "PrintDone" is never fired.

What did you already try to solve it?
The last line in the code shared above I log each event fired. I went to OctoPrint, started a print, it finished, I looked in the log, but it never said "KMG - EVENT NAME: PrintDone" or anything similar.

Additional information about your setup
Latest OctoPi version, CR-10S printer (not that it really matters). Log attached,
octoprint.log (748.3 KB)

The PrinterStateChanged payload does say "Finishing", but then goes straight to "operational" without any actual confirmation whether it finished correctly. I know I'm going into extreme detail here, and it 99.9% of the time means it's succesfully finished when it goes from "finishing" to "operational". It just bothers me that the "PrintFinished" event doesn't work :sweat_smile:

It'd also be awesome if "PrinterStateChanged" took the heating into account. So that it doesn't go from "operational" straight to "printing", but "heating" then "printing". Otherwise you have to call /api/printer and look at the temperature[bed][actual] and temperature[tool0][actual] to manually check whether it's fully heated.

Just a suggestion, @foosel :slight_smile: Might not be the right place to submit it, if not; please do tell me where to do so!

@AlbertMN,

My guess is you are cancelling a print, but expecting the PRINT_DONE event to fire. This does not happen. I believe PRINT_DONE only fires after the completion of a print, not after cancel. To test this you can slice something very tiny, like a 1x1mm cube, and print that to completion, and you should see PRINT_DONE fire.

If you want to know when a print ends, you'll need to capture more events and call your own on_print_end function. Specifically you'll need PRINT_FAILED AND PRINT_DONE.

First, you may want to import 'Events' like so:
from octoprint.events import Events

Then you can change your if statements to something like this:

            if event == Events.PRINT_FAILED:
                self.on_print_end()
            elif event == Events.PRINT_DONE:
                self.on_print_end()

That way you know you are using the correct event name (which it looks like you are). Notice the elif, which is more efficient than using all ifs.

Regarding heater detection, this is a bit tricky, but could be done by watching the gcode. I don't think something like this belongs in OctoPrint itself since it's probably not going to be 100% reliable (there are lots of reasons for this, but basically it comes down to custom start gcode). It might be possible to get this working based on your particular use case, though (let me know what it is).

Let me know if that helps!

I have tested with finished prints and cancelled ones using a very tiny print - same result (the results I based my post on in the first place). I believe the event system is imported, but I only wrote a few lines of code on this. The rest is @jneilliii 's "IP Notify" plugin :slight_smile:
I'll have a look when I'm at my PC again, but I do believe the event doesn't get fired at all.

I looked at the log (didn't notice it before) and saw this at the very end:

Traceback (most recent call last):
  File "/home/pi/oprint/local/lib/python2.7/site-packages/octoprint/plugin/__init__.py", line 225, in call_plugin
    result = getattr(plugin, method)(*args, **kwargs)
  File "/home/pi/oprint/local/lib/python2.7/site-packages/octoprint_KMGMakerspace/__init__.py", line 40, in on_event
    self._logger.info("Told server that the print is finished, response: " + webresponse)
TypeError: cannot concatenate 'str' and 'instance' objects

Change this line

self._logger.info("Told server that the print is finished, response: " + webresponse)

to this

self._logger.info("Told server that the print is finished")

and try it again. There are lots of errors in the log. You might want to wrap your function in a try/except and put a breakpoint within the 'except' so you can see when an error is thrown.