Skip to content


regex_command = re.compile('^\\s*((?P<codeGM>[GM]\\d+)(\\.(?P<subcode>\\d+))?|(?P<codeT>T)\\d+|(?P<codeF>F)\\d+)') module-attribute #

Regex for a GCODE command.

regex_e_positions = re.compile(f'E(?P<id>\d+):\s*(?P<value>{regex_float_pattern})') module-attribute #

Regex for matching multiple E coordinates in a position report.

Groups will be as follows
  • id: id of the extruder or which the position is reported
  • value: reported position value

regex_firmware_splitter = re.compile('(^|\\s+)([A-Z][A-Z0-9_]*):') module-attribute #

Regex to use for splitting M115 responses.

regex_float = re.compile(regex_float_pattern) module-attribute #

Regex for a float value.

regex_marlinKillError = re.compile('Heating failed|Thermal Runaway|MAXTEMP triggered|MINTEMP triggered|Invalid extruder number|Watchdog barked|KILL caused') module-attribute #

Regex matching first line of kill causing errors from Marlin.

regex_minMaxError = re.compile('Error:[0-9]\\n') module-attribute #

Regex matching first line of min/max errors from the firmware.

regex_position = re.compile('X:\\s*(?P<x>{float})\\s*Y:\\s*(?P<y>{float})\\s*Z:\\s*(?P<z>{float})\\s*((E:\\s*(?P<e>{float}))|(?P<es>(E\\d+:\\s*{float}\\s*)+))'.format(float=regex_float_pattern)) module-attribute #

Regex for matching position reporting.

Groups will be as follows
  • x: X coordinate
  • y: Y coordinate
  • z: Z coordinate
  • e: E coordinate if present, or
  • es: multiple E coordinates if present, to be parsed further with regex_e_positions

regex_repetierTempBed = re.compile('TargetBed:(?P<target>%s)' % regex_float_pattern) module-attribute #

Regex for matching target temp reporting from Repetier for beds.

Groups will be as follows
  • target: new target temperature (float)

regex_repetierTempExtr = re.compile('TargetExtr(?P<toolnum>\\d+):(?P<target>%s)' % regex_float_pattern) module-attribute #

Regex for matching target temp reporting from Repetier.

Groups will be as follows
  • toolnum: number of the extruder to which the target temperature report belongs (int)
  • target: new target temperature (float)

regex_resend_linenumber = re.compile('(N|N:)?(?P<n>%s)' % regex_int_pattern) module-attribute #

Regex to use for request line numbers in resend requests

regex_sdFileOpened = re.compile('File opened:\\s*(?P<name>.*?)\\s+Size:\\s*(?P<size>%s)' % regex_int_pattern) module-attribute #

Regex matching "File opened" messages from the firmware.

Groups will be as follows
  • name: name of the file reported as having been opened (str)
  • size: size of the file in bytes (int)

regex_sdPrintingByte = re.compile('(?P<current>[0-9]+)/(?P<total>[0-9]+)') module-attribute #

Regex matching SD printing status reports.

Groups will be as follows
  • current: current byte position in file being printed
  • total: total size of file being printed

regex_serial_devices = re.compile('^(?:ttyUSB|ttyACM|tty\\.usb|cu\\.|cuaU|ttyS|rfcomm).*') module-attribute #

Regex used to filter out valid tty devices

regex_temp = re.compile('(^|\\s)(?P<sensor>B|C|T(?P<toolnum>\\d*)|([\\w]+)):\\s*(?P<actual>%s)(\\s*\\/?\\s*(?P<target>%s))?' % (regex_float_pattern, regex_float_pattern)) module-attribute #

Regex matching temperature entries in line.

Groups will be as follows
  • sensor: whole sensor designator, incl. optional toolnum, e.g. "T1", "B", "C" or anything custom (str)
  • toolnum: tool number, if provided, only for T0, T1, etc (int)
  • actual: actual temperature (float)
  • target: target temperature, if provided (float)

regexes_parameters = {'floatE': re.compile('(^|[^A-Za-z])[Ee](?P<value>%s)' % regex_float_pattern), 'floatF': re.compile('(^|[^A-Za-z])[Ff](?P<value>%s)' % regex_float_pattern), 'floatP': re.compile('(^|[^A-Za-z])[Pp](?P<value>%s)' % regex_float_pattern), 'floatR': re.compile('(^|[^A-Za-z])[Rr](?P<value>%s)' % regex_float_pattern), 'floatS': re.compile('(^|[^A-Za-z])[Ss](?P<value>%s)' % regex_float_pattern), 'floatX': re.compile('(^|[^A-Za-z])[Xx](?P<value>%s)' % regex_float_pattern), 'floatY': re.compile('(^|[^A-Za-z])[Yy](?P<value>%s)' % regex_float_pattern), 'floatZ': re.compile('(^|[^A-Za-z])[Zz](?P<value>%s)' % regex_float_pattern), 'intN': re.compile('(^|[^A-Za-z])[Nn](?P<value>%s)' % regex_int_pattern), 'intS': re.compile('(^|[^A-Za-z])[Ss](?P<value>%s)' % regex_int_pattern), 'intT': re.compile('(^|[^A-Za-z])[Tt](?P<value>%s)' % regex_int_pattern)} module-attribute #

Regexes for parsing various GCODE command parameters.

MachineCom(port = None, baudrate = None, callbackObject = None, printerProfileManager = None) #

close(is_error = False, wait = True, timeout = 10.0, *args, **kwargs) #

Closes the connection to the printer.

If is_error is False, will attempt to send the beforePrinterDisconnected gcode script. If is_error is False and wait is True, will wait until all messages in the send queue (including the beforePrinterDisconnected gcode script) have been sent to the printer.


  • is_error (bool) –

    Whether the closing takes place due to an error (True) or not (False, default)

  • wait (bool) –

    Whether to wait for all messages in the send queue to be processed before closing (True, default) or not (False)

PrintingFileInformation(filename, user = None) #

Encapsulates information regarding the current file being printed: file name, current position, total size and time the print started. Allows to reset the current file position to 0 and to calculate the current progress as a floating point value between 0 and 1.

close() #

Closes the print job.

getProgress() #

The current progress of the file, calculated as relation between file position and absolute size. Returns -1 if file size is None or < 1.

reset() #

Resets the current file position to 0.

start() #

Marks the print job as started and remembers the start time.

PrintingGcodeFileInformation(filename, offsets_callback = None, current_tool_callback = None, user = None) #

Bases: PrintingFileInformation

Encapsulates information regarding an ongoing direct print. Takes care of the needed file handle and ensures that the file is closed in case of an error.

close() #

Closes the file if it's still open.

getNext() #

Retrieves the next line for printing.

start() #

Opens the file for reading and determines the file size.

PrintingSdFileInformation(filename, size, user = None) #

Bases: PrintingFileInformation

Encapsulates information regarding an ongoing print from SD.

SpecialStreamingGcodeFileInformation #

Bases: StreamingGcodeFileInformation

For streaming files to the printer that aren't GCODE.

Difference to regular StreamingGcodeFileInformation: no checksum requirement, only rudimentary line processing (stripping of whitespace from the end and ignoring of empty lines)

canonicalize_temperatures(parsed, current) #

Canonicalizes the temperatures provided in parsed.

Will make sure that returned result only contains extruder keys like Tn, so always qualified with a tool number.

The algorithm for cleaning up the parsed keys is the following
  • If T is not included with the reported extruders, return
  • If more than just T is reported:
  • If both T and T0 are reported, remove T from the result.
  • Else set T0 to T and delete T (Smoothie extra).
  • If only T is reported, set Tc to T and delete T
  • return


  • parsed (dict) –

    the parsed temperatures (mapping tool => (actual, target)) to canonicalize

  • current (int) –

    the current active extruder


  • dict

    the canonicalized version of parsed

gcode_command_for_cmd(cmd) #

Tries to parse the provided cmd and extract the GCODE command identifier from it (e.g. "G0" for "G0 X10.0").


  • cmd (str) –

    The command to try to parse.


  • str or None: The GCODE command identifier if it could be parsed, or None if not.

parse_capability_line(line) #

Parses the provided firmware capability line.

Lines are expected to be of the format

Cap:<capability name in caps>:<0 or 1>




  • line (str) –

    the line to parse


  • tuple

    a 2-tuple of the parsed capability name and whether it's on (true) or off (false), or None if the line could not be parsed

parse_firmware_line(line) #

Parses the provided firmware info line.

The result will be a dictionary mapping from the contained keys to the contained values.

Valid keys must only contain A-Z, 0-9 and _ and must start with a letter. See the unit tests for valid and invalid examples. There sadly is no existing specification of the key format, but this is the format extracted from real life logs.


  • line (str) –

    the line to parse


  • dict

    a dictionary with the parsed data

parse_position_line(line) #

Parses the provided M114 response line and returns the parsed coordinates.


  • line (str) –

    the line to parse


  • dict or None: the parsed coordinates, or None if no coordinates could be parsed

parse_resend_line(line) #

Parses the provided resend line and returns requested line number.


  • line (str) –

    the line to parse


  • int or None: the extracted line number to resend, or None if no number could be extracted

parse_temperature_line(line, current) #

Parses the provided temperature line.

The result will be a dictionary mapping from the extruder or bed key to a tuple with current and target temperature. The result will be canonicalized with :func:canonicalize_temperatures before returning.


  • line (str) –

    the temperature line to parse

  • current (int) –

    the current active extruder


  • tuple

    a 2-tuple with the maximum tool number and a dict mapping from key to (actual, target) tuples, with key either matching Tn for n >= 0 or B

upload_cli() #

Uploads to on SD card of printer on port , using baudrate .