From 93bbedae869f9e74294d4c8083702faa80ac0a71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Mon, 30 Nov 2015 11:11:35 +0100 Subject: [PATCH] Only process bed temps & commands if printer profile has heated bed Solves #1125 --- docs/api/printer.rst | 20 +++++-- docs/features/gcode_scripts.rst | 17 ++++-- src/octoprint/server/api/printer.py | 53 +++++++++++-------- src/octoprint/settings.py | 5 +- .../static/js/app/viewmodels/temperature.js | 21 ++++---- src/octoprint/util/comm.py | 9 +++- 6 files changed, 82 insertions(+), 43 deletions(-) diff --git a/docs/api/printer.rst b/docs/api/printer.rst index 48072249..1184965f 100644 --- a/docs/api/printer.rst +++ b/docs/api/printer.rst @@ -25,7 +25,8 @@ Tool See :ref:`sec-api-printer-toolcommand`. Bed Bed commands allow setting the temperature and temperature offset for the printer's heated bed. Querying the - corresponding resource returns temperature information including an optional history. + corresponding resource returns temperature information including an optional history. Note that Bed commands + are only available if the currently selected printer profile has a heated bed. See :ref:`sec-api-printer-bedcommand`. SD card SD commands allow initialization, refresh and release of the printer's SD card (if available). Querying the @@ -564,6 +565,9 @@ Issue a bed command Upon success, a status code of :http:statuscode:`204` and an empty body is returned. + If no heated bed is configured for the currently selected printer profile, the resource will return + an :http:statuscode:`409`. + **Example Target Temperature Request** Set the target temperature for the printer's heated bed to 75°C. @@ -610,7 +614,8 @@ Issue a bed command :statuscode 204: No error :statuscode 400: If ``target`` or ``offset`` is not a valid number or outside of the supported range, or if the request is otherwise invalid. - :statuscode 409: If the printer is not operational. + :statuscode 409: If the printer is not operational or the selected printer profile + does not have a heated bed. .. _sec-api-printer-bedstate: @@ -627,6 +632,9 @@ Retrieve the current bed state Returns a :http:statuscode:`200` with a Temperature Response in the body upon success. + If no heated bed is configured for the currently selected printer profile, the resource will return + an :http:statuscode:`409`. + .. note:: If you want both tool and bed temperature information at the same time, take a look at :ref:`Retrieve the current printer state `. @@ -675,7 +683,8 @@ Retrieve the current bed state :query limit: If set to an integer (``n``), only the last ``n`` data points from the printer's temperature history will be returned. Will be ignored if ``history`` is not enabled. :statuscode 200: No error - :statuscode 409: If the printer is not operational. + :statuscode 409: If the printer is not operational or the selected printer profile + does not have a heated bed. .. _sec-api-printer-sdcommand: @@ -856,7 +865,7 @@ Send an arbitrary command to the printer .. sourcecode:: http HTTP/1.1 204 No Content - + :json string command: Single command to send to the printer, mutually exclusive with ``commands``. :json string commands: List of commands to send to the printer, mutually exclusive with ``command``. :statuscode 204: No error @@ -913,7 +922,8 @@ Temperature State * - ``bed`` - 0..1 - :ref:`Temperature Data ` - - Current temperature stats for the printer's heated bed. Not included if querying only tool state. + - Current temperature stats for the printer's heated bed. Not included if querying only tool state or if + the currently selected printer profile does not have a heated bed. * - ``history`` - 0..1 - List of :ref:`Historic Temperature Datapoint ` diff --git a/docs/features/gcode_scripts.rst b/docs/features/gcode_scripts.rst index 011e15c3..d1b5fde8 100644 --- a/docs/features/gcode_scripts.rst +++ b/docs/features/gcode_scripts.rst @@ -86,7 +86,7 @@ Out of the box, OctoPrint defaults to the following script setup for ``afterPrin ;disable all heaters {% snippet 'disable_hotends' %} - M140 S0 + [% snippet 'disable_bed' %} ;disable fan M106 S0 @@ -100,8 +100,19 @@ The ``disable_hotends`` snippet is defined as follows: M104 T{{ tool }} S0 {% endfor %} -As you can see, the ``disable_hotends`` snippet utilizes the ``printer_profile`` context variable in order to -iterate through all available extruders and set their temperature to 0. +The ``disable_bed`` snippet is defined as follows: + +.. code-block:: jinja + :caption: Default ``disable_bed`` snippet + + {% if printer_profile.heatedBed %} + M140 S0 + {% endif %} + +As you can see, the ``disable_hotends`` and ``disable_bed`` snippets utilize the +``printer_profile`` context variable in order to iterate through all available +extruders and set their temperature to 0, and to also set the bed temperature +to 0 if a heated bed is configured. .. seealso:: diff --git a/src/octoprint/server/api/printer.py b/src/octoprint/server/api/printer.py index f544b833..d22aefff 100644 --- a/src/octoprint/server/api/printer.py +++ b/src/octoprint/server/api/printer.py @@ -10,10 +10,9 @@ from werkzeug.exceptions import BadRequest import re from octoprint.settings import settings, valid_boolean_trues -from octoprint.server import printer, NO_CONTENT +from octoprint.server import printer, printerProfileManager, NO_CONTENT from octoprint.server.api import api from octoprint.server.util.flask import restricted_access, get_json_command_from_request -import octoprint.util as util from octoprint.printer import UnknownScript @@ -34,9 +33,13 @@ def printerState(): result = {} + processor = lambda x: x + if not printerProfileManager.get_current_or_default()["heatedBed"]: + processor = _delete_bed + # add temperature information if not "temperature" in excludes: - result.update({"temperature": _getTemperatureData(lambda x: x)}) + result.update({"temperature": _get_temperature_data(processor)}) # add sd information if not "sd" in excludes and settings().getBoolean(["feature", "sdSupport"]): @@ -145,14 +148,7 @@ def printerToolState(): if not printer.is_operational(): return make_response("Printer is not operational", 409) - def deleteBed(x): - data = dict(x) - - if "bed" in data.keys(): - del data["bed"] - return data - - return jsonify(_getTemperatureData(deleteBed)) + return jsonify(_get_temperature_data(_delete_bed)) ##~~ Heated bed @@ -164,6 +160,9 @@ def printerBedCommand(): if not printer.is_operational(): return make_response("Printer is not operational", 409) + if not printerProfileManager.get_current_or_default()["heatedBed"]: + return make_response("Printer does not have a heated bed", 409) + valid_commands = { "target": ["target"], "offset": ["offset"] @@ -204,15 +203,10 @@ def printerBedState(): if not printer.is_operational(): return make_response("Printer is not operational", 409) - def deleteTools(x): - data = dict(x) + if not printerProfileManager.get_current_or_default()["heatedBed"]: + return make_response("Printer does not have a heated bed", 409) - for k in data.keys(): - if k.startswith("tool"): - del data[k] - return data - - data = _getTemperatureData(deleteTools) + data = _get_temperature_data(_delete_tools) if isinstance(data, Response): return data else: @@ -382,7 +376,7 @@ def getCustomControls(): return jsonify(controls=customControls) -def _getTemperatureData(filter): +def _get_temperature_data(preprocessor): if not printer.is_operational(): return make_response("Printer is not operational", 409) @@ -399,8 +393,23 @@ def _getTemperatureData(filter): limit = min(limit, len(history)) tempData.update({ - "history": map(lambda x: filter(x), history[-limit:]) + "history": map(lambda x: preprocessor(x), history[-limit:]) }) - return filter(tempData) + return preprocessor(tempData) + +def _delete_tools(x): + return _delete_from_data(x, lambda k: k.startswith("tool")) + + +def _delete_bed(x): + return _delete_from_data(x, lambda k: k == "bed") + + +def _delete_from_data(x, key_matcher): + data = dict(x) + for k in data.keys(): + if key_matcher(k): + del data[k] + return data diff --git a/src/octoprint/settings.py b/src/octoprint/settings.py index a7137e14..929afa24 100644 --- a/src/octoprint/settings.py +++ b/src/octoprint/settings.py @@ -253,9 +253,10 @@ default_settings = { }, "scripts": { "gcode": { - "afterPrintCancelled": "; disable motors\nM84\n\n;disable all heaters\n{% snippet 'disable_hotends' %}\nM140 S0\n\n;disable fan\nM106 S0", + "afterPrintCancelled": "; disable motors\nM84\n\n;disable all heaters\n{% snippet 'disable_hotends' %}\n{% snippet 'disable_bed' %}\n;disable fan\nM106 S0", "snippets": { - "disable_hotends": "{% for tool in range(printer_profile.extruder.count) %}M104 T{{ tool }} S0\n{% endfor %}" + "disable_hotends": "{% for tool in range(printer_profile.extruder.count) %}M104 T{{ tool }} S0\n{% endfor %}", + "disable_bed": "{% if printer_profile.heatedBed %}M140 S0\n{% endif %}" } } }, diff --git a/src/octoprint/static/js/app/viewmodels/temperature.js b/src/octoprint/static/js/app/viewmodels/temperature.js index 9b58d2ec..e05cfd6a 100644 --- a/src/octoprint/static/js/app/viewmodels/temperature.js +++ b/src/octoprint/static/js/app/viewmodels/temperature.js @@ -36,7 +36,7 @@ $(function() { self.heaterOptions = ko.observable({}); - self._numExtrudersUpdated = function() { + self._printerProfileUpdated = function() { var graphColors = ["red", "orange", "green", "brown", "purple"]; var heaterOptions = {}; var tools = self.tools(); @@ -69,15 +69,21 @@ $(function() { } // print bed - heaterOptions["bed"] = {name: gettext("Bed"), color: "blue"}; + if (self.settingsViewModel.printerProfiles.currentProfileData().heatedBed()) { + self.hasBed(true); + heaterOptions["bed"] = {name: gettext("Bed"), color: "blue"}; + } else { + self.hasBed(false); + } // write back self.heaterOptions(heaterOptions); self.tools(tools); }; self.settingsViewModel.printerProfiles.currentProfileData.subscribe(function() { - self._numExtrudersUpdated(); - self.settingsViewModel.printerProfiles.currentProfileData().extruder.count.subscribe(self._numExtrudersUpdated); + self._printerProfileUpdated(); + self.settingsViewModel.printerProfiles.currentProfileData().extruder.count.subscribe(self._printerProfileUpdated); + self.settingsViewModel.printerProfiles.currentProfileData().heatedBed.subscribe(self._printerProfileUpdated()); }); self.temperatures = []; @@ -152,11 +158,8 @@ $(function() { } if (lastData.hasOwnProperty("bed")) { - self.hasBed(true); self.bedTemp["actual"](lastData.bed.actual); self.bedTemp["target"](lastData.bed.target); - } else { - self.hasBed(false); } if (!CONFIG_TEMPERATURE_GRAPH) return; @@ -208,8 +211,6 @@ $(function() { if (!d[type]) return; result[type].actual.push([time, d[type].actual]); result[type].target.push([time, d[type].target]); - - self.hasBed(self.hasBed() || (type == "bed")); }) }); @@ -375,4 +376,4 @@ $(function() { ["loginStateViewModel", "settingsViewModel"], "#temp" ]); -}); \ No newline at end of file +}); diff --git a/src/octoprint/util/comm.py b/src/octoprint/util/comm.py index 9023a006..e9618a6a 100644 --- a/src/octoprint/util/comm.py +++ b/src/octoprint/util/comm.py @@ -1729,6 +1729,12 @@ class MachineCom(object): if self.isPrinting() and not self.isSdPrinting(): self.setPause(True) + def _gcode_M140_queuing(self, cmd, cmd_type=None): + if not self._printerProfileManager.get_current_or_default()["heatedBed"]: + self._log("Warn: Not sending \"{}\", printer profile has no heated bed".format(cmd)) + return None, # Don't send bed commands if we don't have a heated bed + _gcode_M190_queuing = _gcode_M140_queuing + def _gcode_M104_sent(self, cmd, cmd_type=None): toolNum = self._currentTool toolMatch = regexes_parameters["intT"].search(cmd) @@ -1802,7 +1808,8 @@ class MachineCom(object): # are going to shutdown the connection in a second anyhow. for tool in range(self._printerProfileManager.get_current_or_default()["extruder"]["count"]): self._doIncrementAndSendWithChecksum("M104 T{tool} S0".format(tool=tool)) - self._doIncrementAndSendWithChecksum("M140 S0") + if self._printerProfileManager.get_current_or_default()["heatedBed"]: + self._doIncrementAndSendWithChecksum("M140 S0") # close to reset host state self._errorValue = "Closing serial port due to emergency stop M112."