From baab1ce70aff2c7653b6255979081dd44119e338 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Fri, 11 Mar 2016 17:18:48 +0100 Subject: [PATCH] Use new generic TypedQueue for send queue and command queue That way no M105 cascades can be triggered by the M105 polling timer (or the M27 polling timer). Adjusted logging output to make clear which queue rejected typed entry. Made timeout handler send M105 with type "temperature" as well to make sure we don't suddenly have two M105 directly after each other in the send_queue, one from the polling timer, one from the timeout handler. Fixes #1275 --- src/octoprint/util/comm.py | 54 +++++++++----------------------------- 1 file changed, 12 insertions(+), 42 deletions(-) diff --git a/src/octoprint/util/comm.py b/src/octoprint/util/comm.py index fb26c5bb..d07f50f1 100644 --- a/src/octoprint/util/comm.py +++ b/src/octoprint/util/comm.py @@ -24,7 +24,8 @@ from octoprint.settings import settings, default_settings from octoprint.events import eventManager, Events from octoprint.filemanager import valid_file_type from octoprint.filemanager.destinations import FileDestinations -from octoprint.util import get_exception_string, sanitize_ascii, filter_non_ascii, CountedEvent, RepeatedTimer, to_unicode, bom_aware_open +from octoprint.util import get_exception_string, sanitize_ascii, filter_non_ascii, CountedEvent, RepeatedTimer, \ + to_unicode, bom_aware_open, TypedQueue, TypeAlreadyInQueue try: import _winreg @@ -214,7 +215,7 @@ class MachineCom(object): self._temp = {} self._bedTemp = None self._tempOffsets = dict() - self._commandQueue = queue.Queue() + self._command_queue = TypedQueue() self._currentZ = None self._heatupWaitStartTime = None self._heatupWaitTimeLost = 0.0 @@ -533,7 +534,10 @@ class MachineCom(object): return if self.isPrinting() and not self.isSdFileSelected(): - self._commandQueue.put((cmd, cmd_type)) + try: + self._command_queue.put((cmd, cmd_type), item_type=cmd_type) + except TypeAlreadyInQueue as e: + self._logger.debug("Type already in command queue: " + e.type) elif self.isOperational() or force: self._sendCommand(cmd, cmd_type=cmd_type) @@ -1240,7 +1244,7 @@ class MachineCom(object): else: self._log("Communication timeout while printing, trying to trigger response from printer. " + general_message) - self._sendCommand("M105") + self._sendCommand("M105", cmd_type="temperature") self._clear_to_send.set() return @@ -1332,11 +1336,11 @@ class MachineCom(object): # from the queue, we'll send the second (if there is one). We do not # want to get stuck here by throwing away commands. while True: - if self._commandQueue.empty() or self.isStreaming(): + if self._command_queue.empty() or self.isStreaming(): # no command queue or irrelevant command queue => return return False - entry = self._commandQueue.get() + entry = self._command_queue.get() if isinstance(entry, tuple): if not len(entry) == 2: # something with that entry is broken, ignore it and fetch @@ -1691,9 +1695,9 @@ class MachineCom(object): """ try: - self._send_queue.put((command, linenumber, command_type)) + self._send_queue.put((command, linenumber, command_type), item_type=command_type) except TypeAlreadyInQueue as e: - self._logger.debug("Type already in queue: " + e.type) + self._logger.debug("Type already in send queue: " + e.type) def _send_loop(self): """ @@ -2269,40 +2273,6 @@ class StreamingGcodeFileInformation(PrintingGcodeFileInformation): return process_gcode_line(line) -class TypedQueue(queue.Queue): - - def __init__(self, maxsize=0): - queue.Queue.__init__(self, maxsize=maxsize) - self._lookup = [] - - def _put(self, item): - if isinstance(item, tuple) and len(item) == 3: - cmd, line, cmd_type = item - if cmd_type is not None: - if cmd_type in self._lookup: - raise TypeAlreadyInQueue(cmd_type, "Type {cmd_type} is already in queue".format(**locals())) - else: - self._lookup.append(cmd_type) - - queue.Queue._put(self, item) - - def _get(self): - item = queue.Queue._get(self) - - if isinstance(item, tuple) and len(item) == 3: - cmd, line, cmd_type = item - if cmd_type is not None and cmd_type in self._lookup: - self._lookup.remove(cmd_type) - - return item - - -class TypeAlreadyInQueue(Exception): - def __init__(self, t, *args, **kwargs): - Exception.__init__(self, *args, **kwargs) - self.type = t - - def get_new_timeout(type, intervals): now = time.time() return now + intervals.get(type, 0.0)