Merge branch 'maintenance' into devel

Conflicts:
	CHANGELOG.md
	docs/configuration/config_yaml.rst
	src/octoprint/plugins/virtual_printer/virtual.py
	src/octoprint/server/__init__.py
	src/octoprint/settings.py
	src/octoprint/static/js/app/dataupdater.js
	src/octoprint/static/js/app/viewmodels/settings.js
	src/octoprint/templates/dialogs/settings/serialconnection.jinja2
	src/octoprint/util/comm.py
This commit is contained in:
Gina Häußge 2016-03-16 11:12:06 +01:00
commit 7bdc4418fd
20 changed files with 1043 additions and 406 deletions

60
.github/ISSUE_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,60 @@
Please read the "guidelines for contributing" that are linked ^-- just
up there. Also read the FAQ: https://github.com/foosel/OctoPrint/wiki/FAQ.
This is a bug and feature tracker, please only use it to report bugs
or request features within OctoPrint (not OctoPi, not any OctoPrint
plugins and not unofficial OctoPrint versions). Mark requests with
a [Request] prefix in the title please. Fully fill out the bug reporting
template for bug reports.
Do not seek support here ("I need help with ..."), that belongs on
the mailing list or the G+ community (both linked in the "guidelines
for contributing" linked above, read it!), NOT here.
Thank you!
----
#### What were you doing?
[Please be as specific as possible here. The maintainers will need to reproduce
your issue in order to fix it and that is not possible if they don't know
what you did to get it to happen in the first place. If you encountered
a problem with specific files of any sorts, make sure to also include a link to a file
with which to reproduce the problem.]
#### What did you expect to happen?
#### What happened instead?
#### Branch & Commit or Version of OctoPrint
[Can be found in the lower left corner of the web interface.]
#### Printer model & used firmware incl. version
[If applicable, always include if unsure.]
#### Browser and Version of Browser, Operating System running Browser
[If applicable, always include if unsure.]
#### Link to octoprint.log
[On gist.github.com or pastebin.com. Always include and never truncate.]
#### Link to contents of terminal tab or serial.log
[On gist.github.com or pastebin.com. If applicable, always include if unsure or
reporting communication issues. Never truncate.]
#### Link to contents of Javascript console in the browser
[On gist.github.com or pastebin.com or alternatively a screenshot. If applicable -
always include if unsure or reporting UI issues.]
#### Screenshot(s) showing the problem:
[If applicable. Always include if unsure or reporting UI issues.]
I have read the FAQ.

50
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,50 @@
Thank you for your interest into contributing to OctoPrint, it's
highly appreciated!
Please make sure you have read the "guidelines for contributing" as
linked just above this form, there's a section on Pull Requests in there
as well that contains important information.
As a summary, please make sure you have ticked all points on this
checklist:
* [ ] Your changes are not possible to do through a plugin and relevant
to a large audience (ideally all users of OctoPrint)
* [ ] If your changes are large or otherwise disruptive: You have
made sure your changes don't interfere with current development by
talking it through with the maintainers, e.g. through a
Brainstorming ticket
* [ ] Your PR targets OctoPrint's devel branch (not master,
maintenance or anything else)
* [ ] Your PR was opened from a custom branch on your repository
(no PRs from your version of master, maintenance or devel please),
e.g. dev/my_new_feature
* [ ] Your PR only contains relevant changes: no unrelated files,
no dead code, ideally only one commit - rebase your PR if necessary!
* [ ] Your changes follow the coding style
* [ ] If your changes include style sheets: You have modified the
.less source files, not the .css files (those are generated with
lessc)
* [ ] You have tested your changes (please state how!) - ideally you
have added unit tests
* [ ] You have run the existing unit tests against your changes and
nothing broke
* [ ] You have added yourself to the AUTHORS.md file :)
Feel free to delete all this help text, then describe
your PR further. You may use the template provided below to do that.
The more details the better!
----
#### What does this PR do and why is it necessary?
#### How was it tested? How can it be tested by the reviewer?
#### Any background context you want to provide?
#### What are the relevant tickets if any?
#### Screenshots (if appropriate)
#### Further notes

View file

@ -14,11 +14,11 @@ master
HEAD
\(detached.*
# maintenance is currently the branch for preparation of maintenance release 1.2.10
# maintenance is currently the branch for preparation of maintenance release 1.2.11
# so are any fix/... and improve/... branches
maintenance 1.2.10 abe68adac8f465a31bf4f3f3933190c1fc242cda pep440-dev
fix/.* 1.2.10 abe68adac8f465a31bf4f3f3933190c1fc242cda pep440-dev
improve/.* 1.2.10 abe68adac8f465a31bf4f3f3933190c1fc242cda pep440-dev
maintenance 1.2.11 692166f067329cd3d6fdc84389e0dd76184c5e0c pep440-dev
fix/.* 1.2.11 692166f067329cd3d6fdc84389e0dd76184c5e0c pep440-dev
improve/.* 1.2.11 692166f067329cd3d6fdc84389e0dd76184c5e0c pep440-dev
# every other branch is a development branch and thus gets resolved to 1.3.0-dev for now
.* 1.3.0 198d3450d94be1a2 pep440-dev

View file

@ -60,6 +60,7 @@ date of first contribution):
* ["bwgan"](https://github.com/bwgan)
* [Siim Raud](https://github.com/2ndalpha)
* ["geoporalis"](https://github.com/geoporalis)
* [Andrew Malota](https://github.com/2bitoperations)
OctoPrint started off as a fork of [Cura](https://github.com/daid/Cura) by
[Daid Braam](https://github.com/daid). Parts of its communication layer and

View file

@ -69,6 +69,34 @@
* [#1047](https://github.com/foosel/OctoPrint/issues/1047) - Fixed 90 degree
webcam rotation for iOS Safari.
## 1.2.10 (2016-03-16)
### Improvements
* Improved performance of console output during plugin installation/deinstallation
* Slight performance improvements in the communication layer
* Log small log excerpt to `octoprint.log` upon encountering a communication error.
* Changed wording in "firmware error" notifications to better reflect that there was an error while communicating with the printer, since the error condition can also be triggered by serial errors while trying to establish a connection to the printer or when already connected.
* Support downloading ".mp4" timelapse files. You'll need a [custom wrapper script for timelapse rendering](https://github.com/guysoft/OctoPi/issues/184) for this to be relevant to you. See also [#1255](https://github.com/foosel/OctoPrint/pull/1255)
* The communication layer will now wait up to 10s after clicking disconnect in order to send any left-over lines from its buffers.
* Moved less commonly used configuration options in Serial settings into "Advanced options" roll-out.
### Bug Fixes
* [#1224](https://github.com/foosel/OctoPrint/issues/1224) - Fixed an issue introduced by the fix for [#1196](https://github.com/foosel/OctoPrint/issues/1196) that had the "Upload to SD" button stop working correctly.
* [#1226](https://github.com/foosel/OctoPrint/issues/1226) - Fixed an issue causing an error on disconnect after or cancelling of an SD print, caused by the unsuccessful attempt to record print recovery data for the file on the printer's SD card.
* [#1268](https://github.com/foosel/OctoPrint/issues/1268) - Only add bed temperature line to temperature management specific start gcode in CuraEngine invocation if a bed temperature is actually set in the slicing profile.
* [#1271](https://github.com/foosel/OctoPrint/issues/1271) - If a communication timeout occurs during an active resend request, OctoPrint will now not send an `M105` with an increased line number anymore but repeat the last resent command instead.
* [#1272](https://github.com/foosel/OctoPrint/issues/1272) - Don't add an extra `ok` for `M28` response.
* [#1273](https://github.com/foosel/OctoPrint/issues/1273) - Add an extra `ok` for `M29` response, but only if configured such in "Settings" > "Serial" > "Advanced options" > "Generate additional ok for M29"
* [#1274](https://github.com/foosel/OctoPrint/issues/1274) - Trigger `M20` only once after finishing uploading to SD
* [#1275](https://github.com/foosel/OctoPrint/issues/1275) - Prevent `M105` "cascade" due to communication timeouts
* Fixed wrong tracking of extruder heating up for `M109 Tn` commands in multi-extruder setups.
* Fixed start of SD file uploads not sending an `M110`.
* Fixed job data not being reset when disconnecting while printing.
([Commits](https://github.com/foosel/OctoPrint/compare/1.2.9...1.2.10))
## 1.2.9 (2016-02-10)
### Improvements

View file

@ -106,12 +106,26 @@ following section *completely*. Thank you! :)
fixing it. Take the time to filter through possible duplicates and be really
sure that your problem definitely is a new one. Try more than one search query
(e.g. do not only search for "webcam" if you happen to run into an issue
with your webcam, also search for "timelapse" etc).
with your webcam, also search for "timelapse" etc). Do not only read the subject lines
of tickets that look like they might be related, but also read the ticket itself!
**Very important:** Please make absolutely sure that if you find a bug that looks like
it is the same as your's, it actually behaves the same as your's. E.g. if someone gives steps
to reproduce his bug that looks like your's, reproduce the bug like that if possible,
and only add a "me too" if you actually can reproduce the same
issue. Also **provide all information** as [described below](#what-should-i-include-in-a-bug-report)
and whatever was additionally requested over the course of the ticket
even if you "only" add to an existing ticket. The more information available regarding a bug, the higher
the chances of reproducing and solving it. But "me too" on an actually unrelated ticket
makes it more difficult due to on top of having to figure out the original problem
there's now also a [red herring](https://en.wikipedia.org/wiki/Red_herring) interfering - so please be
very diligent here!
### What should I include in a bug report?
Always use the following template (you can remove what's within `[...]`, that's
only provided here as some additional information for you):
only provided here as some additional information for you), **even if only adding a
"me too" to an existing ticket**:
#### What were you doing?
@ -157,6 +171,8 @@ only provided here as some additional information for you):
I have read the FAQ.
Copy-paste this template **completely**. Do not skip any lines!
### Where can I find which version and branch I'm on?
You can find out all of them by taking a look into the lower left corner of the
@ -216,43 +232,67 @@ See [How to open the Javascript Console in different browsers](https://webmaster
implement your feature as a plugin, create a "Brainstorming" ticket to get
the discussion going on how best to solve *this* in OctoPrint's plugin
system - maybe that's the actual PR you have been waiting for to contribute :)
2. If you plan to make **any large changes to the code or appearance, please
open a "Brainstorming" ticket first** so that we can determine if it's a
good time for your specific pull request. It might be that we're currently
in the process of making heavy changes to the code locations you'd target
as well, or your approach doesn't fit the general "project vision", and
that would just cause unnecessary work and frustration for everyone or
2. If you plan to make **any large or otherwise disruptive changes to the
code or appearance, please open a "Brainstorming" ticket first** so
that we can determine if it's a good time for your specific pull
request. It might be that we're currently in the process of making
heavy changes to the code locations you'd target as well, or your
approach doesn't fit the general "project vision", and that would
just cause unnecessary work and frustration for everyone or
possibly get the PR rejected.
3. Create your pull request **from a custom branch** on your end (e.g.
`dev/myNewFeature`)[1] **against the `devel` branch**. Create **one pull request
per feature/bug fix**. If your PR contains an important bug fix, we will
make sure to backport it to the `maintenance` branch to also include it in
the next release.
4. Make sure you **follow the current coding style**. This means:
4. Make sure there are **only relevant changes** included in your PR. No
changes to unrelated files, no additional files that don't belong (e.g.
commits of your full virtual environment). Make sure your PR consists
**ideally of only one commit** (use git's rebase and squash functionality).
5. Make sure you **follow the current coding style**. This means:
* Tabs instead of spaces in the Python files[2]
* Spaces instead of tabs in the Javascript sources
* English language (code, variables, comments, ...)
* Comments where necessary: Tell *why* the code does something like it does
it, structure your code
* Following the general architecture
If your PR needs to make changes to the Stylesheets, change the ``.less`` files
from which the CSS is compiled.
5. **Test your changes thoroughly**. That also means testing with usage
* If your PR needs to make changes to the Stylesheets, change the
``.less`` files from which the CSS is compiled.
* Make sure you do not add dead code (e.g. commented out left-overs
from experiments).
6. Ensure your changes **pass the existing unit tests**. PRs that break
those cannot be accepted.
7. **Test your changes thoroughly**. That also means testing with usage
scenarios you don't normally use, e.g. if you only use access control, test
without and vice versa. If you only test with your printer, test with the
virtual printer and vice versa. State in your pull request how you tested
your changes. Ideally **add unit tests** - OctoPrint severely lacks in that
department, but we are trying to change that, so any new code already covered
with a test suite helps a lot!
6. In your pull request's description, **state what your pull request does**,
8. In your pull request's description, **state what your pull request does**,
as in, what feature does it implement, what bug does it fix. The more
thoroughly you explain your intent behind the PR here, the higher the
chances it will get merged fast.
7. Important: Don't forget to **add yourself to the [AUTHORS](./AUTHORS.md)
chances it will get merged fast. There is a template provided below
that can help you here.
9. Don't forget to **add yourself to the [AUTHORS](./AUTHORS.md)
file** :)
Template to use for Pull Request descriptions:
```
#### What does this PR do and why is it necessary?
#### How was it tested? How can it be tested by the reviewer?
#### Any background context you want to provide?
#### What are the relevant tickets if any?
#### Screenshots (if appropriate)
#### Further notes
```
## What do the branches mean?
There are three main branches in OctoPrint:
@ -324,6 +364,9 @@ the local version identifier to allow for an exact determination of the active c
* 2015-12-01: Heavily reworked to include examples, better structure and
all information in one document.
* 2016-02-10: Added information about branch structure and versioning.
* 2016-02-16: Added requirement to add information from template to existing
tickets as well, explained issue with "me too" red herrings.
* 2016-03-14: Some more requirements for PRs, and a PR template.
## Footnotes
* [1] - If you are wondering why, the problem is that anything that you add

View file

@ -50,7 +50,7 @@ defaults = dict(
wall_thickness=0.8,
solid_layer_thickness=0.6,
print_temperature=[220, 0, 0, 0],
print_bed_temperature=70,
print_bed_temperature=0,
platform_adhesion=PlatformAdhesionTypes.NONE,
filament_diameter=[2.85, 0, 0, 0],
filament_flow=100.0,

View file

@ -72,6 +72,7 @@ class VirtualPrinter(object):
self._selectedSdFileSize = None
self._selectedSdFilePos = None
self._writingToSd = False
self._writingToSdHandle = None
self._newSdFilePos = None
self._heatupThread = None
@ -84,6 +85,8 @@ class VirtualPrinter(object):
self._echoOnM117 = settings().getBoolean(["devel", "virtualPrinter", "echoOnM117"])
self._brokenM29 = settings().getBoolean(["devel", "virtualPrinter", "brokenM29"])
self.currentLine = 0
self.lastN = 0
@ -100,6 +103,10 @@ class VirtualPrinter(object):
self._killed = False
self._triggerResendAt100 = True
self._triggerResendWithTimeoutAt105 = True
self._triggeredResendWithTimeoutAt105 = False
readThread = threading.Thread(target=self._processIncoming)
readThread.start()
@ -154,6 +161,10 @@ class VirtualPrinter(object):
linenumber = int(re.search("N([0-9]+)", data).group(1))
self.lastN = linenumber
self.currentLine = linenumber
self._triggerResendAt100 = True
self._triggerResendWithTimeoutAt105 = True
self._sendOk()
continue
elif data.startswith("N"):
@ -162,10 +173,18 @@ class VirtualPrinter(object):
if linenumber != expected:
self._triggerResend(actual=linenumber)
continue
elif self.currentLine == 101:
elif linenumber == 100 and self._triggerResendAt100:
# simulate a resend at line 100
self._triggerResendAt100 = False
self._triggerResend(expected=100)
continue
elif linenumber == 105 and self._triggerResendWithTimeoutAt105 and not self._writingToSd:
# simulate a resend with timeout at line 105
self._triggerResendWithTimeoutAt105 = False
self._triggerResend(expected=105)
self._dont_answer = True
self.lastN = linenumber
continue
else:
self.lastN = linenumber
data = data.split(None, 1)[1].strip()
@ -173,9 +192,8 @@ class VirtualPrinter(object):
data += "\n"
# shortcut for writing to SD
if self._writingToSd and not self._selectedSdFile is None and not "M29" in data:
with open(self._selectedSdFile, "a") as f:
f.write(data)
if self._writingToSdHandle is not None and not "M29" in data:
self._writingToSdHandle.write(data)
self._sendOk()
continue
@ -696,60 +714,89 @@ class VirtualPrinter(object):
else:
self._send("error writing to file")
handle = None
try:
handle = open(file, "w")
except:
self.outgoing.put("error writing to file")
if handle is not None:
try:
handle.close()
except:
pass
self._writingToSdHandle = handle
self._writingToSd = True
self._selectedSdFile = file
self._send("Writing to file: %s" % filename)
def _finishSdFile(self):
try:
self._writingToSdHandle.close()
except:
pass
finally:
self._writingToSdHandle = None
self._writingToSd = False
self._selectedSdFile = None
self.outgoing.put("Done saving file")
def _sdPrintingWorker(self):
self._selectedSdFilePos = 0
with open(self._selectedSdFile, "r") as f:
for line in iter(f.readline, ""):
if self._killed:
break
try:
with open(self._selectedSdFile, "r") as f:
for line in iter(f.readline, ""):
if self._killed:
break
# reset position if requested by client
if self._newSdFilePos is not None:
f.seek(self._newSdFilePos)
self._newSdFilePos = None
# reset position if requested by client
if self._newSdFilePos is not None:
f.seek(self._newSdFilePos)
self._newSdFilePos = None
# read current file position
self._selectedSdFilePos = f.tell()
# read current file position
self._selectedSdFilePos = f.tell()
# if we are paused, wait for unpausing
self._sdPrintingSemaphore.wait()
# if we are paused, wait for unpausing
self._sdPrintingSemaphore.wait()
# set target temps
if 'M104' in line or 'M109' in line:
self._parseHotendCommand(line)
if 'M140' in line or 'M190' in line:
self._parseBedCommand(line)
# set target temps
if 'M104' in line or 'M109' in line:
self._parseHotendCommand(line)
elif 'M140' in line or 'M190' in line:
self._parseBedCommand(line)
elif line.startswith("G0") or line.startswith("G1") or line.startswith("G2") or line.startswith("G3"):
# simulate reprap buffered commands via a Queue with maxsize which internally simulates the moves
self.buffered.put(line)
time.sleep(settings().getFloat(["devel", "virtualPrinter", "throttle"]))
except AttributeError:
if self.outgoing is not None:
raise
self._sdPrintingSemaphore.clear()
self._selectedSdFilePos = 0
self._sdPrinter = None
self._send("Done printing file")
if not self._killed:
self._sdPrintingSemaphore.clear()
self._selectedSdFilePos = 0
self._sdPrinter = None
self.outgoing.put("Done printing file")
def _waitForHeatup(self, heater):
delta = 1
delay = 1
if heater.startswith("tool"):
toolNum = int(heater[len("tool"):])
while not self._killed and (self.temp[toolNum] < self.targetTemp[toolNum] - delta or self.temp[toolNum] > self.targetTemp[toolNum] + delta):
self._simulateTemps(delta=delta)
self._send("T:%0.2f" % self.temp[toolNum])
time.sleep(delay)
elif heater == "bed":
while not self._killed and (self.bedTemp < self.bedTargetTemp - delta or self.bedTemp > self.bedTargetTemp + delta):
self._simulateTemps(delta=delta)
self._send("B:%0.2f" % self.bedTemp)
time.sleep(delay)
try:
if heater.startswith("tool"):
toolNum = int(heater[len("tool"):])
while not self._killed and (self.temp[toolNum] < self.targetTemp[toolNum] - delta or self.temp[toolNum] > self.targetTemp[toolNum] + delta):
self._simulateTemps(delta=delta)
self.outgoing.put("T:%0.2f" % self.temp[toolNum])
time.sleep(delay)
elif heater == "bed":
while not self._killed and (self.bedTemp < self.bedTargetTemp - delta or self.bedTemp > self.bedTargetTemp + delta):
self._simulateTemps(delta=delta)
self.outgoing.put("B:%0.2f" % self.bedTemp)
time.sleep(delay)
except AttributeError:
if self.outgoing is not None:
raise
def _deleteSdFile(self, filename):
if filename.startswith("/"):
@ -817,13 +864,13 @@ class VirtualPrinter(object):
try:
line = self.outgoing.get(timeout=self._read_timeout)
time.sleep(settings().getFloat(["devel", "virtualPrinter", "throttle"]))
self._seriallog.info(">>> {}".format(line.strip()))
return line
except Queue.Empty:
return ""
def close(self):
self._killed = True
self.incoming = None
self.outgoing = None
self.buffered = None

View file

@ -17,7 +17,7 @@ import time
from octoprint import util as util
from octoprint.events import eventManager, Events
from octoprint.filemanager import FileDestinations
from octoprint.filemanager import FileDestinations, NoSuchStorage
from octoprint.plugin import plugin_manager, ProgressPlugin
from octoprint.printer import PrinterInterface, PrinterCallback, UnknownScript
from octoprint.printer.estimation import TimeEstimationHelper
@ -62,10 +62,6 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback):
self._currentZ = None
self._progress = None
self._printTime = None
self._printTimeLeft = None
self._printAfterSelect = False
self._posAfterSelect = None
@ -93,7 +89,8 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback):
on_update=self._sendCurrentDataCallbacks,
on_add_temperature=self._sendAddTemperatureCallbacks,
on_add_log=self._sendAddLogCallbacks,
on_add_message=self._sendAddMessageCallbacks
on_add_message=self._sendAddMessageCallbacks,
on_get_progress=self._updateProgressDataCallback
)
self._stateMonitor.reset(
state={"text": self.get_state_string(), "flags": self._getStateFlags()},
@ -366,7 +363,7 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback):
self._printAfterSelect = printAfterSelect
self._posAfterSelect = pos
self._comm.selectFile("/" + path if sd else path, sd)
self._setProgressData(0, None, None, None)
self._setProgressData(completion=0)
self._setCurrentZ(None)
def unselect_file(self):
@ -374,7 +371,7 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback):
return
self._comm.unselectFile()
self._setProgressData(0, None, None, None)
self._setProgressData(completion=0)
self._setCurrentZ(None)
def start_print(self, pos=None):
@ -405,7 +402,7 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback):
self._fileManager.delete_recovery_data()
self._lastProgressReport = None
self._setProgressData(0, None, None, None)
self._setProgressData(completion=0)
self._setCurrentZ(None)
self._comm.startPrint(pos=pos)
@ -429,7 +426,7 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback):
# reset progress, height, print time
self._setCurrentZ(None)
self._setProgressData(None, None, None, None)
self._setProgressData()
# mark print as failure
if self._selectedFile is not None:
@ -608,7 +605,24 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback):
return result
def _setProgressData(self, progress, filepos, printTime, cleanedPrintTime):
def _setProgressData(self, completion=None, filepos=None, printTime=None, printTimeLeft=None):
self._stateMonitor.set_progress(dict(completion=int(completion * 100) if completion is not None else None,
filepos=filepos,
printTime=int(printTime) if printTime is not None else None,
printTimeLeft=int(printTimeLeft) if printTimeLeft is not None else None))
def _updateProgressDataCallback(self):
if self._comm is None:
progress = None
filepos = None
printTime = None
cleanedPrintTime = None
else:
progress = self._comm.getPrintProgress()
filepos = self._comm.getPrintFilepos()
printTime = self._comm.getPrintTime()
cleanedPrintTime = self._comm.getCleanedPrintTime()
estimatedTotalPrintTime = self._estimateTotalPrintTime(progress, cleanedPrintTime)
totalPrintTime = estimatedTotalPrintTime
@ -624,16 +638,7 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback):
sub_progress = 1.0
totalPrintTime = (1 - sub_progress) * statisticalTotalPrintTime + sub_progress * estimatedTotalPrintTime
self._progress = progress
self._printTime = printTime
self._printTimeLeft = totalPrintTime - cleanedPrintTime if (totalPrintTime is not None and cleanedPrintTime is not None) else None
self._stateMonitor.set_progress({
"completion": self._progress * 100 if self._progress is not None else None,
"filepos": filepos,
"printTime": int(self._printTime) if self._printTime is not None else None,
"printTimeLeft": int(self._printTimeLeft) if self._printTimeLeft is not None else None
})
printTimeLeft = totalPrintTime - cleanedPrintTime if (totalPrintTime is not None and cleanedPrintTime is not None) else None
if progress:
progress_int = int(progress * 100)
@ -641,6 +646,10 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback):
self._lastProgressReport = progress_int
self._reportPrintProgressToPlugins(progress_int)
return dict(completion=progress * 100 if progress is not None else None,
filepos=filepos,
printTime=int(printTime) if printTime is not None else None,
printTimeLeft=int(printTimeLeft) if printTimeLeft is not None else None)
def _addTemperatureData(self, temp, bedTemp):
currentTimeUtc = int(time.time())
@ -795,11 +804,12 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback):
self._analysisQueue.resume() # printing done, put those cpu cycles to good use
elif state == comm.MachineCom.STATE_PRINTING:
self._analysisQueue.pause() # do not analyse files while printing
elif state == comm.MachineCom.STATE_CLOSED or state == comm.MachineCom.STATE_CLOSED_WITH_ERROR:
if state == comm.MachineCom.STATE_CLOSED or state == comm.MachineCom.STATE_CLOSED_WITH_ERROR:
if self._comm is not None:
self._comm = None
self._setProgressData(0, None, None, None)
self._setProgressData(completion=0)
self._setCurrentZ(None)
self._setJobData(None, None, None)
self._printerProfileManager.deselect()
@ -820,7 +830,7 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback):
Triggers storage of new values for printTime, printTimeLeft and the current progress.
"""
self._setProgressData(self._comm.getPrintProgress(), self._comm.getPrintFilepos(), self._comm.getPrintTime(), self._comm.getCleanedPrintTime())
self._stateMonitor.trigger_progress_update()
def on_comm_z_change(self, newZ):
"""
@ -850,7 +860,7 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback):
def on_comm_print_job_done(self):
self._fileManager.log_print(FileDestinations.SDCARD if self._selectedFile["sd"] else FileDestinations.LOCAL, self._selectedFile["filename"], time.time(), self._comm.getPrintTime(), True, self._printerProfileManager.get_current_or_default()["id"])
self._setProgressData(1.0, self._selectedFile["filesize"], self._comm.getPrintTime(), 0)
self._setProgressData(completion=1.0, filepos=self._selectedFile["filesize"], printTime=self._comm.getPrintTime(), printTimeLeft=0)
self._stateMonitor.set_state({"text": self.get_state_string(), "flags": self._getStateFlags()})
self._fileManager.delete_recovery_data()
@ -858,7 +868,7 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback):
self._sdStreaming = True
self._setJobData(filename, filesize, True)
self._setProgressData(0.0, 0, 0, None)
self._setProgressData(completion=0.0, filepos=0, printTime=0)
self._stateMonitor.set_state({"text": self.get_state_string(), "flags": self._getStateFlags()})
def on_comm_file_transfer_done(self, filename):
@ -871,22 +881,28 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback):
self._setCurrentZ(None)
self._setJobData(None, None, None)
self._setProgressData(None, None, None, None)
self._setProgressData()
self._stateMonitor.set_state({"text": self.get_state_string(), "flags": self._getStateFlags()})
def on_comm_force_disconnect(self):
self.disconnect()
def on_comm_record_fileposition(self, origin, name, pos):
self._fileManager.save_recovery_data(origin, name, pos)
try:
self._fileManager.save_recovery_data(origin, name, pos)
except NoSuchStorage:
pass
except:
self._logger.exception("Error while trying to persist print recovery data")
class StateMonitor(object):
def __init__(self, interval=0.5, on_update=None, on_add_temperature=None, on_add_log=None, on_add_message=None):
def __init__(self, interval=0.5, on_update=None, on_add_temperature=None, on_add_log=None, on_add_message=None, on_get_progress=None):
self._interval = interval
self._update_callback = on_update
self._on_add_temperature = on_add_temperature
self._on_add_log = on_add_log
self._on_add_message = on_add_message
self._on_get_progress = on_get_progress
self._state = None
self._job_data = None
@ -895,16 +911,24 @@ class StateMonitor(object):
self._current_z = None
self._progress = None
self._progress_dirty = False
self._offsets = {}
self._change_event = threading.Event()
self._state_lock = threading.Lock()
self._progress_lock = threading.Lock()
self._last_update = time.time()
self._worker = threading.Thread(target=self._work)
self._worker.daemon = True
self._worker.start()
def _get_current_progress(self):
if callable(self._on_get_progress):
return self._on_get_progress()
return self._progress
def reset(self, state=None, job_data=None, progress=None, current_z=None):
self.set_state(state)
self.set_job_data(job_data)
@ -936,9 +960,16 @@ class StateMonitor(object):
self._job_data = job_data
self._change_event.set()
def trigger_progress_update(self):
with self._progress_lock:
self._progress_dirty = True
self._change_event.set()
def set_progress(self, progress):
self._progress = progress
self._change_event.set()
with self._progress_lock:
self._progress_dirty = False
self._progress = progress
self._change_event.set()
def set_temp_offsets(self, offsets):
self._offsets = offsets
@ -948,19 +979,24 @@ class StateMonitor(object):
while True:
self._change_event.wait()
with self._state_lock:
now = time.time()
delta = now - self._last_update
additional_wait_time = self._interval - delta
if additional_wait_time > 0:
time.sleep(additional_wait_time)
now = time.time()
delta = now - self._last_update
additional_wait_time = self._interval - delta
if additional_wait_time > 0:
time.sleep(additional_wait_time)
with self._state_lock:
data = self.get_current_data()
self._update_callback(data)
self._last_update = time.time()
self._change_event.clear()
def get_current_data(self):
with self._progress_lock:
if self._progress_dirty:
self._progress = self._get_current_progress()
self._progress_dirty = False
return {
"state": self._state,
"job": self._job_data,

View file

@ -93,6 +93,7 @@ def getSettings():
"helloCommand": s.get(["serial", "helloCommand"]),
"ignoreErrorsFromFirmware": s.getBoolean(["serial", "ignoreErrorsFromFirmware"]),
"disconnectOnErrors": s.getBoolean(["serial", "disconnectOnErrors"]),
"triggerOkForM29": s.getBoolean(["serial", "triggerOkForM29"])
},
"folder": {
"uploads": s.getBaseFolder("uploads"),
@ -246,6 +247,7 @@ def _saveSettings(data):
if "helloCommand" in data["serial"]: s.set(["serial", "helloCommand"], data["serial"]["helloCommand"])
if "ignoreErrorsFromFirmware" in data["serial"]: s.setBoolean(["serial", "ignoreErrorsFromFirmware"], data["serial"]["ignoreErrorsFromFirmware"])
if "disconnectOnErrors" in data["serial"]: s.setBoolean(["serial", "disconnectOnErrors"], data["serial"]["disconnectOnErrors"])
if "triggerOkForM29" in data["serial"]: s.setBoolean(["serial", "triggerOkForM29"], data["serial"]["triggerOkForM29"])
oldLog = s.getBoolean(["serial", "log"])
if "log" in data["serial"].keys(): s.setBoolean(["serial", "log"], data["serial"]["log"])

View file

@ -91,7 +91,11 @@ default_settings = {
"checksumRequiringCommands": ["M110"],
"helloCommand": "M110 N0",
"disconnectOnErrors": True,
"ignoreErrorsFromFirmware": False
"ignoreErrorsFromFirmware": False,
"logResends": False,
# command specific flags
"triggerOkForM29": True
},
"server": {
"host": "0.0.0.0",
@ -315,6 +319,7 @@ default_settings = {
"waitInterval": 1.0,
"supportM112": True,
"echoOnM117": True,
"brokenM29": True,
"supportF": False
}
}

View file

@ -289,16 +289,16 @@ function DataUpdater(allViewModels) {
} else if (type == "PrintCancelled") {
if (payload.firmwareError) {
new PNotify({
title: gettext("Unhandled firmware error"),
text: _.sprintf(gettext("The firmware reported an unhandled error. Due to that the ongoing print job was cancelled. Error: %(firmwareError)s"), payload),
title: gettext("Unhandled communication error"),
text: _.sprintf(gettext("There was an unhandled error while talking to the printer. Due to that the ongoing print job was cancelled. Error: %(firmwareError)s"), payload),
type: "error",
hide: false
});
}
} else if (type == "Error") {
new PNotify({
title: gettext("Unhandled firmware error"),
text: _.sprintf(gettext("The firmware reported an unhandled error. Due to that OctoPrint disconnected. Error: %(error)s"), payload),
title: gettext("Unhandled communication error"),
text: _.sprintf(gettext("The was an unhandled error while talking to the printer. Due to that OctoPrint disconnected. Error: %(error)s"), payload),
type: "error",
hide: false
});

View file

@ -145,6 +145,7 @@ $(function() {
self.serial_helloCommand = ko.observable(undefined);
self.serial_ignoreErrorsFromFirmware = ko.observable(undefined);
self.serial_disconnectOnErrors = ko.observable(undefined);
self.serial_triggerOkForM29 = ko.observable(undefined);
self.folder_uploads = ko.observable(undefined);
self.folder_timelapse = ko.observable(undefined);

View file

@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: OctoPrint\n"
"Report-Msgid-Bugs-To: i18n@octoprint.org\n"
"POT-Creation-Date: 2016-02-10 11:12+0100\n"
"PO-Revision-Date: 2016-02-10 11:25+0100\n"
"POT-Creation-Date: 2016-03-16 09:14+0100\n"
"PO-Revision-Date: 2016-03-16 09:21+0100\n"
"Last-Translator: Gina Häußge <osd@foosel.net>\n"
"Language: de\n"
"Language-Team: German (http://www.transifex.com/projects/p/octoprint/language/de/)\n"
@ -521,6 +521,7 @@ msgstr "Das sieht nicht aus wie ein valides Pluginarchiv. Valide Pluginarchive s
#: src/octoprint/plugins/pluginmanager/templates/pluginmanager_settings.jinja2:182
#: src/octoprint/plugins/softwareupdate/templates/softwareupdate_settings.jinja2:63
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:96
#: src/octoprint/templates/tabs/terminal.jinja2:27
msgid "Advanced options"
msgstr "Erweiterte Optionen"
@ -1041,18 +1042,18 @@ msgstr "%(local)s nach %(remote)s gestreamt, dauerte %(time).2f Sekunden"
#: src/octoprint/static/js/app/dataupdater.js:352
#: src/octoprint/static/js/app/dataupdater.js:360
msgid "Unhandled firmware error"
msgstr "Unbehandelter Fehler der Firmware"
msgid "Unhandled communication error"
msgstr "Unbehandelter Kommunikationsfehler"
#: src/octoprint/static/js/app/dataupdater.js:353
#, python-format
msgid "The firmware reported an unhandled error. Due to that the ongoing print job was cancelled. Error: %(firmwareError)s"
msgstr "Die Firmware hat einen durch OctoPrint unbehandelten Fehler gemeldet. Daher wurder der laufende Druckauftrag abgebrochen. Fehler: %(firmwareError)s"
msgid "There was an unhandled error while talking to the printer. Due to that the ongoing print job was cancelled. Error: %(firmwareError)s"
msgstr "Es gab einen unbehandelten Fehler bei der Kommunikation mit dem Drucker. Daher wurder der laufende Druckauftrag abgebrochen. Fehler: %(firmwareError)s"
#: src/octoprint/static/js/app/dataupdater.js:361
#, python-format
msgid "The firmware reported an unhandled error. Due to that OctoPrint disconnected. Error: %(error)s"
msgstr "Die Firmware hat einen durch OctoPrint unbehandelten Fehler gemeldet. Daher hat OctoPrint die Verbindung getrennt. Fehler: %(error)s"
msgid "The was an unhandled error while talking to the printer. Due to that OctoPrint disconnected. Error: %(error)s"
msgstr "Es gab einen unbehandelten Fehler bei der Kommunikation mit dem Drucker. Daher hat OctoPrint die Verbindung getrennt. Fehler: %(error)s"
#: src/octoprint/static/js/app/helpers.js:385
#, python-format
@ -1923,7 +1924,7 @@ msgstr "Falls der freie Plattenplatz unter diese Schwellwerte fallen sollte wird
#: src/octoprint/templates/dialogs/settings/folders.jinja2:47
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:69
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:97
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:90
#: src/octoprint/templates/tabs/gcodeviewer.jinja2:66
#: src/octoprint/templates/tabs/timelapse.jinja2:13
msgid "Warning"
@ -2132,30 +2133,66 @@ msgid "Log communication to serial.log (might negatively impact performance)"
msgstr "Logge die Kommunikation in das serial.log (kann die Performance negativ beeinflussen)"
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:74
msgid "Long running commands"
msgstr "Lang laufende Befehle"
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:77
msgid "Use this to specify the commands known to take a long time to complete without output from your printer and hence might cause timeout issues. Just the G or M code, comma separated."
msgstr "Nutze diese Option, um solche Befehle zu definieren, von denen Du weißt, dass sie eine längere Zeit lang laufen, währenddessen keinen Output produzieren und daher Timeoutprobleme verursachen könnten. Nur den G- oder M-Code, kommasepariert."
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:81
msgid "Additional serial ports"
msgstr "Zusätzliche serielle Ports"
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:84
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:77
#, python-format
msgid "Use this to define additional <a href=\"%%(glob_url)s\">glob patterns</a> matching serial ports to list for connecting against, e.g. <code>/dev/ttyAMA*</code>. One entry per line."
msgstr "Nutze diese Einstellung um zusätzliche <a href=\"%%(glob_url)s\">glob patterns</a> zu konfigurieren, die auf serielle Ports deines Druckers matchen, z.B. <code>/dev/ttyAMA*</code>. Ein Eintrag pro Zeile."
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:90
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:83
msgid "Not only cancel ongoing prints but also disconnect on unhandled errors from the firmware."
msgstr "Bei unbehalten Firmwarefehlern nicht nur den Druckauftrag abbrechen, sondern auch die Verbindung zum Drucker trennen."
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:97
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:90
msgid "Ignore any unhandled errors from the firmware. Only use this if your firmware sends stuff prefixed with \"Error\" that is not an actual error. Might mask printer issues, be careful!"
msgstr "Alle unbehalten Firmwarefehler ignorieren. Nur nutzen wenn Deine Firmware Dinge mit \"Error\" sendet die nicht wirklich Fehler sind. Könnte Druckerprobleme maskieren, vorsicht!"
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:98
msgid "Command to send to the firmware on first handshake attempt."
msgstr "Kommando, das als erster Handshakeversuch an die Firmware gesendet werden soll"
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:99
msgid "\"Hello\" command"
msgstr "\"Hallo\"-Befehl"
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:102
msgid "Use this to specify a different command than the default <code>M110</code> to send to the printer on initial connection to trigger a communication handshake."
msgstr "Nutze diese Einstellung um einen anderen Befehl als <code>M110</code> beim initialen Verbindungsaufbau zum drucker zu senden."
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:105
msgid "Commands that are know to run long and hence should suppress communication timeouts from being triggered."
msgstr "Befehle, von denen bekannt ist, dass sie lang zur Ausführung benötigen und daher das Auslösen von Kommunikationstimeouts unterdrücken sollten."
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:106
msgid "Long running commands"
msgstr "Lang laufende Befehle"
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:109
msgid "Use this to specify the commands known to take a long time to complete without output from your printer and hence might cause timeout issues. Just the G or M code, comma separated."
msgstr "Nutze diese Option, um solche Befehle zu definieren, von denen Du weißt, dass sie eine längere Zeit lang laufen, währenddessen keinen Output produzieren und daher Timeoutprobleme verursachen könnten. Nur den G- oder M-Code, kommasepariert."
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:112
msgid "Commands that always require a line number and checksum to be sent with them."
msgstr "Befehle, die immer mit einer Prüfsumme und Zeilennummer gesendet werden müssen."
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:113
msgid "Commands that always require a checksum"
msgstr "Befehle, die immer eine Prüfsumme benötigen"
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:116
msgid "Use this to specify which commands <strong>always</strong> need to be sent with a checksum. Comma separated list."
msgstr "Nutze diese Einstellung um Befehle zu spezifizieren, die <strong>immer</strong> mit Prüfsumme gesendet werden müssen. Komma-separierte Liste."
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:121
msgid "Generate additional <code>ok</code> for <code>M29</code>"
msgstr "Zusätzliches <code>ok</code> für <code>M29</code> generieren"
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:121
msgid "Most Marlin < v1.1.0"
msgstr "Viele Marlin < v1.1.0"
#: src/octoprint/templates/dialogs/settings/server.jinja2:2
msgid "Commands"
msgstr "Befehle"

View file

@ -18,6 +18,7 @@ import threading
from functools import wraps
import warnings
import contextlib
import Queue as queue
logger = logging.getLogger(__name__)
@ -877,12 +878,9 @@ class RepeatedTimer(threading.Thread):
class CountedEvent(object):
def __init__(self, value=0, max=None, name=None):
logger_name = __name__ + ".CountedEvent" + (".{name}".format(name=name) if name is not None else "")
self._logger = logging.getLogger(logger_name)
def __init__(self, value=0, maximum=None, **kwargs):
self._counter = 0
self._max = max
self._max = kwargs.get("max", maximum)
self._mutex = threading.Lock()
self._event = threading.Event()
@ -907,17 +905,14 @@ class CountedEvent(object):
return self._counter == 0
def _internal_set(self, value):
self._logger.debug("New counter value: {value}".format(value=value))
self._counter = value
if self._counter <= 0:
self._counter = 0
self._event.clear()
self._logger.debug("Cleared event")
else:
if self._max is not None and self._counter > self._max:
self._counter = self._max
self._event.set()
self._logger.debug("Set event")
class InvariantContainer(object):
@ -951,3 +946,43 @@ class InvariantContainer(object):
def __iter__(self):
return self._data.__iter__()
class TypedQueue(queue.Queue):
def __init__(self, maxsize=0):
queue.Queue.__init__(self, maxsize=maxsize)
self._lookup = set()
def put(self, item, item_type=None, *args, **kwargs):
queue.Queue.put(self, (item, item_type), *args, **kwargs)
def get(self, *args, **kwargs):
item, _ = queue.Queue.get(self, *args, **kwargs)
return item
def _put(self, item):
_, item_type = item
if item_type is not None:
if item_type in self._lookup:
raise TypeAlreadyInQueue(item_type, "Type {} is already in queue".format(item_type))
else:
self._lookup.add(item_type)
queue.Queue._put(self, item)
def _get(self):
item = queue.Queue._get(self)
_, item_type = item
if item_type is not None:
self._lookup.discard(item_type)
return item
class TypeAlreadyInQueue(Exception):
def __init__(self, t, *args, **kwargs):
Exception.__init__(self, *args, **kwargs)
self.type = t

File diff suppressed because it is too large Load diff

View file

@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: OctoPrint\n"
"Report-Msgid-Bugs-To: i18n@octoprint.org\n"
"POT-Creation-Date: 2016-02-10 11:12+0100\n"
"PO-Revision-Date: 2016-02-10 11:25+0100\n"
"POT-Creation-Date: 2016-03-16 09:14+0100\n"
"PO-Revision-Date: 2016-03-16 09:21+0100\n"
"Last-Translator: Gina Häußge <osd@foosel.net>\n"
"Language: de\n"
"Language-Team: German (http://www.transifex.com/projects/p/octoprint/language/de/)\n"
@ -521,6 +521,7 @@ msgstr "Das sieht nicht aus wie ein valides Pluginarchiv. Valide Pluginarchive s
#: src/octoprint/plugins/pluginmanager/templates/pluginmanager_settings.jinja2:182
#: src/octoprint/plugins/softwareupdate/templates/softwareupdate_settings.jinja2:63
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:96
#: src/octoprint/templates/tabs/terminal.jinja2:27
msgid "Advanced options"
msgstr "Erweiterte Optionen"
@ -1041,18 +1042,18 @@ msgstr "%(local)s nach %(remote)s gestreamt, dauerte %(time).2f Sekunden"
#: src/octoprint/static/js/app/dataupdater.js:352
#: src/octoprint/static/js/app/dataupdater.js:360
msgid "Unhandled firmware error"
msgstr "Unbehandelter Fehler der Firmware"
msgid "Unhandled communication error"
msgstr "Unbehandelter Kommunikationsfehler"
#: src/octoprint/static/js/app/dataupdater.js:353
#, python-format
msgid "The firmware reported an unhandled error. Due to that the ongoing print job was cancelled. Error: %(firmwareError)s"
msgstr "Die Firmware hat einen durch OctoPrint unbehandelten Fehler gemeldet. Daher wurder der laufende Druckauftrag abgebrochen. Fehler: %(firmwareError)s"
msgid "There was an unhandled error while talking to the printer. Due to that the ongoing print job was cancelled. Error: %(firmwareError)s"
msgstr "Es gab einen unbehandelten Fehler bei der Kommunikation mit dem Drucker. Daher wurder der laufende Druckauftrag abgebrochen. Fehler: %(firmwareError)s"
#: src/octoprint/static/js/app/dataupdater.js:361
#, python-format
msgid "The firmware reported an unhandled error. Due to that OctoPrint disconnected. Error: %(error)s"
msgstr "Die Firmware hat einen durch OctoPrint unbehandelten Fehler gemeldet. Daher hat OctoPrint die Verbindung getrennt. Fehler: %(error)s"
msgid "The was an unhandled error while talking to the printer. Due to that OctoPrint disconnected. Error: %(error)s"
msgstr "Es gab einen unbehandelten Fehler bei der Kommunikation mit dem Drucker. Daher hat OctoPrint die Verbindung getrennt. Fehler: %(error)s"
#: src/octoprint/static/js/app/helpers.js:385
#, python-format
@ -1923,7 +1924,7 @@ msgstr "Falls der freie Plattenplatz unter diese Schwellwerte fallen sollte wird
#: src/octoprint/templates/dialogs/settings/folders.jinja2:47
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:69
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:97
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:90
#: src/octoprint/templates/tabs/gcodeviewer.jinja2:66
#: src/octoprint/templates/tabs/timelapse.jinja2:13
msgid "Warning"
@ -2132,30 +2133,66 @@ msgid "Log communication to serial.log (might negatively impact performance)"
msgstr "Logge die Kommunikation in das serial.log (kann die Performance negativ beeinflussen)"
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:74
msgid "Long running commands"
msgstr "Lang laufende Befehle"
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:77
msgid "Use this to specify the commands known to take a long time to complete without output from your printer and hence might cause timeout issues. Just the G or M code, comma separated."
msgstr "Nutze diese Option, um solche Befehle zu definieren, von denen Du weißt, dass sie eine längere Zeit lang laufen, währenddessen keinen Output produzieren und daher Timeoutprobleme verursachen könnten. Nur den G- oder M-Code, kommasepariert."
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:81
msgid "Additional serial ports"
msgstr "Zusätzliche serielle Ports"
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:84
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:77
#, python-format
msgid "Use this to define additional <a href=\"%%(glob_url)s\">glob patterns</a> matching serial ports to list for connecting against, e.g. <code>/dev/ttyAMA*</code>. One entry per line."
msgstr "Nutze diese Einstellung um zusätzliche <a href=\"%%(glob_url)s\">glob patterns</a> zu konfigurieren, die auf serielle Ports deines Druckers matchen, z.B. <code>/dev/ttyAMA*</code>. Ein Eintrag pro Zeile."
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:90
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:83
msgid "Not only cancel ongoing prints but also disconnect on unhandled errors from the firmware."
msgstr "Bei unbehalten Firmwarefehlern nicht nur den Druckauftrag abbrechen, sondern auch die Verbindung zum Drucker trennen."
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:97
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:90
msgid "Ignore any unhandled errors from the firmware. Only use this if your firmware sends stuff prefixed with \"Error\" that is not an actual error. Might mask printer issues, be careful!"
msgstr "Alle unbehalten Firmwarefehler ignorieren. Nur nutzen wenn Deine Firmware Dinge mit \"Error\" sendet die nicht wirklich Fehler sind. Könnte Druckerprobleme maskieren, vorsicht!"
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:98
msgid "Command to send to the firmware on first handshake attempt."
msgstr "Kommando, das als erster Handshakeversuch an die Firmware gesendet werden soll"
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:99
msgid "\"Hello\" command"
msgstr "\"Hallo\"-Befehl"
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:102
msgid "Use this to specify a different command than the default <code>M110</code> to send to the printer on initial connection to trigger a communication handshake."
msgstr "Nutze diese Einstellung um einen anderen Befehl als <code>M110</code> beim initialen Verbindungsaufbau zum drucker zu senden."
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:105
msgid "Commands that are know to run long and hence should suppress communication timeouts from being triggered."
msgstr "Befehle, von denen bekannt ist, dass sie lang zur Ausführung benötigen und daher das Auslösen von Kommunikationstimeouts unterdrücken sollten."
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:106
msgid "Long running commands"
msgstr "Lang laufende Befehle"
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:109
msgid "Use this to specify the commands known to take a long time to complete without output from your printer and hence might cause timeout issues. Just the G or M code, comma separated."
msgstr "Nutze diese Option, um solche Befehle zu definieren, von denen Du weißt, dass sie eine längere Zeit lang laufen, währenddessen keinen Output produzieren und daher Timeoutprobleme verursachen könnten. Nur den G- oder M-Code, kommasepariert."
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:112
msgid "Commands that always require a line number and checksum to be sent with them."
msgstr "Befehle, die immer mit einer Prüfsumme und Zeilennummer gesendet werden müssen."
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:113
msgid "Commands that always require a checksum"
msgstr "Befehle, die immer eine Prüfsumme benötigen"
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:116
msgid "Use this to specify which commands <strong>always</strong> need to be sent with a checksum. Comma separated list."
msgstr "Nutze diese Einstellung um Befehle zu spezifizieren, die <strong>immer</strong> mit Prüfsumme gesendet werden müssen. Komma-separierte Liste."
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:121
msgid "Generate additional <code>ok</code> for <code>M29</code>"
msgstr "Zusätzliches <code>ok</code> für <code>M29</code> generieren"
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:121
msgid "Most Marlin < v1.1.0"
msgstr "Viele Marlin < v1.1.0"
#: src/octoprint/templates/dialogs/settings/server.jinja2:2
msgid "Commands"
msgstr "Befehle"

View file

@ -6,9 +6,9 @@
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: OctoPrint 1.2.9.dev71+g92c65cb.dirty\n"
"Project-Id-Version: OctoPrint 1.2.10.dev50+g6305c4d\n"
"Report-Msgid-Bugs-To: i18n@octoprint.org\n"
"POT-Creation-Date: 2016-02-10 11:12+0100\n"
"POT-Creation-Date: 2016-03-16 09:14+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -552,6 +552,7 @@ msgstr ""
#: src/octoprint/plugins/pluginmanager/templates/pluginmanager_settings.jinja2:182
#: src/octoprint/plugins/softwareupdate/templates/softwareupdate_settings.jinja2:63
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:96
#: src/octoprint/templates/tabs/terminal.jinja2:27
msgid "Advanced options"
msgstr ""
@ -1126,21 +1127,21 @@ msgstr ""
#: src/octoprint/static/js/app/dataupdater.js:352
#: src/octoprint/static/js/app/dataupdater.js:360
msgid "Unhandled firmware error"
msgid "Unhandled communication error"
msgstr ""
#: src/octoprint/static/js/app/dataupdater.js:353
#, python-format
msgid ""
"The firmware reported an unhandled error. Due to that the ongoing print "
"job was cancelled. Error: %(firmwareError)s"
"There was an unhandled error while talking to the printer. Due to that "
"the ongoing print job was cancelled. Error: %(firmwareError)s"
msgstr ""
#: src/octoprint/static/js/app/dataupdater.js:361
#, python-format
msgid ""
"The firmware reported an unhandled error. Due to that OctoPrint "
"disconnected. Error: %(error)s"
"The was an unhandled error while talking to the printer. Due to that "
"OctoPrint disconnected. Error: %(error)s"
msgstr ""
#: src/octoprint/static/js/app/helpers.js:385
@ -2038,7 +2039,7 @@ msgstr ""
#: src/octoprint/templates/dialogs/settings/folders.jinja2:47
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:69
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:97
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:90
#: src/octoprint/templates/tabs/gcodeviewer.jinja2:66
#: src/octoprint/templates/tabs/timelapse.jinja2:13
msgid "Warning"
@ -2266,21 +2267,10 @@ msgid "Log communication to serial.log (might negatively impact performance)"
msgstr ""
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:74
msgid "Long running commands"
msgstr ""
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:77
msgid ""
"Use this to specify the commands known to take a long time to complete "
"without output from your printer and hence might cause timeout issues. "
"Just the G or M code, comma separated."
msgstr ""
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:81
msgid "Additional serial ports"
msgstr ""
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:84
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:77
#, python-format
msgid ""
"Use this to define additional <a href=\"%%(glob_url)s\">glob patterns</a>"
@ -2288,19 +2278,75 @@ msgid ""
"<code>/dev/ttyAMA*</code>. One entry per line."
msgstr ""
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:90
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:83
msgid ""
"Not only cancel ongoing prints but also disconnect on unhandled errors "
"from the firmware."
msgstr ""
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:97
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:90
msgid ""
"Ignore any unhandled errors from the firmware. Only use this if your "
"firmware sends stuff prefixed with \"Error\" that is not an actual error."
" Might mask printer issues, be careful!"
msgstr ""
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:98
msgid "Command to send to the firmware on first handshake attempt."
msgstr ""
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:99
msgid "\"Hello\" command"
msgstr ""
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:102
msgid ""
"Use this to specify a different command than the default "
"<code>M110</code> to send to the printer on initial connection to trigger"
" a communication handshake."
msgstr ""
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:105
msgid ""
"Commands that are know to run long and hence should suppress "
"communication timeouts from being triggered."
msgstr ""
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:106
msgid "Long running commands"
msgstr ""
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:109
msgid ""
"Use this to specify the commands known to take a long time to complete "
"without output from your printer and hence might cause timeout issues. "
"Just the G or M code, comma separated."
msgstr ""
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:112
msgid ""
"Commands that always require a line number and checksum to be sent with "
"them."
msgstr ""
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:113
msgid "Commands that always require a checksum"
msgstr ""
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:116
msgid ""
"Use this to specify which commands <strong>always</strong> need to be "
"sent with a checksum. Comma separated list."
msgstr ""
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:121
msgid "Generate additional <code>ok</code> for <code>M29</code>"
msgstr ""
#: src/octoprint/templates/dialogs/settings/serialconnection.jinja2:121
msgid "Most Marlin < v1.1.0"
msgstr ""
#: src/octoprint/templates/dialogs/settings/server.jinja2:2
msgid "Commands"
msgstr ""