Exemplo n.º 1
0
    def test_g28(self):
        # no parameters
        gcode = "G28"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G28")
        self.assertDictEqual({}, parsed.parameters)

        # all parameters, funky spaces
        gcode = "g  2  8 xy zw; some kind of comment"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G28")
        self.assertIsNone(parsed.parameters["X"])
        self.assertIsNone(parsed.parameters["Y"])
        self.assertIsNone(parsed.parameters["Z"])
        self.assertIsNone(parsed.parameters["W"])

        # all parameters, no spaces
        gcode = "g28wzxy; some kind of comment"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G28")
        self.assertIsNone(parsed.parameters["X"])
        self.assertIsNone(parsed.parameters["Y"])
        self.assertIsNone(parsed.parameters["Z"])
        self.assertIsNone(parsed.parameters["W"])

        # some parameters
        gcode = "g28 xy; some kind of comment"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G28")
        self.assertIsNone(parsed.parameters["X"])
        self.assertIsNone(parsed.parameters["Y"])
        self.assertNotIn("Z", parsed.parameters)
        self.assertNotIn("W", parsed.parameters)
Exemplo n.º 2
0
 def test_parse_int_negative(self):
     # test negative F error
     gcode = "G00 F- 1 09 "
     with self.assertRaises(Exception) as context:
         Commands.parse(gcode)
     self.assertTrue(
         "The parameter value is negative, which is not allowed." in
         context.exception)
Exemplo n.º 3
0
 def test_multiple_decimals_command(self):
     # test multiple decimal points in parameter 2
     gcode = "G28.0."
     with self.assertRaises(Exception) as context:
         Commands.parse(gcode)
     self.assertTrue(
         "Cannot parse the gcode address, multiple periods seen." in
         context.exception)
Exemplo n.º 4
0
    def test_unknown_command(self):
        gcode = "G9999fdafdsafdafsd"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G9999")
        self.assertIsNone(parsed.parameters)

        gcode = "G9999"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G9999")
        self.assertIsNone(parsed.parameters)
Exemplo n.º 5
0
    def test_ExtruderMovement(self):
        """Test the M82 and M83 command."""
        position = Position(self.Settings, self.OctoprintPrinterProfile, False)
        previous_pos = Pos(self.Settings.current_printer(), self.OctoprintPrinterProfile)
        # test initial position
        self.assertIsNone(position.e())
        self.assertIsNone(position.is_extruder_relative())
        self.assertIsNone(position.e_relative_pos(previous_pos))

        # set extruder to relative coordinates
        position.update(Commands.parse("M83"))

        # test movement
        previous_pos = Pos(self.Settings.current_printer(), self.OctoprintPrinterProfile, position.get_position())
        position.update(Commands.parse("G0 E100"))
        self.assertEqual(position.e(), 100)
        # this is somewhat reversed from what we do in the position.py module
        # there we update the pos() object and compare to the current state, so
        # comparing the current state to the
        # previous will result in the opposite sign
        self.assertEqual(position.e_relative_pos(previous_pos), -100)

        # switch to absolute movement
        previous_pos = Pos(self.Settings.current_printer(), self.OctoprintPrinterProfile, position.get_position())
        position.update(Commands.parse("M82"))
        self.assertFalse(position.is_extruder_relative())
        self.assertEqual(position.e(), 100)
        self.assertEqual(position.e_relative_pos(previous_pos), 0)

        # move to -25
        previous_pos = Pos(self.Settings.current_printer(), self.OctoprintPrinterProfile, position.get_position())
        position.update(Commands.parse("G0 E-25"))
        self.assertEqual(position.e(), -25)
        self.assertEqual(position.e_relative_pos(previous_pos), 125)

        # test movement to origin
        previous_pos = Pos(self.Settings.current_printer(), self.OctoprintPrinterProfile, position.get_position())
        position.update(Commands.parse("G0 E0"))
        self.assertEqual(position.e(), 0)
        self.assertEqual(position.e_relative_pos(previous_pos), -25)

        # switch to relative position
        previous_pos = Pos(self.Settings.current_printer(), self.OctoprintPrinterProfile, position.get_position())
        position.update(Commands.parse("M83"))
        position.update(Commands.parse("G0 e1.1"))
        self.assertEqual(position.e(), 1.1)
        self.assertEqual(position.e_relative_pos(previous_pos), -1.1)

        # move and test
        previous_pos = Pos(self.Settings.current_printer(), self.OctoprintPrinterProfile, position.get_position())
        position.update(Commands.parse("G0 e1.1"))
        self.assertEqual(position.e(), 2.2)
        self.assertEqual(position.e_relative_pos(previous_pos), -1.1)

        # move and test
        previous_pos = Pos(self.Settings.current_printer(), self.OctoprintPrinterProfile, position.get_position())
        position.update(Commands.parse("G0 e-2.2"))
        self.assertEqual(position.e(), 0)
        self.assertEqual(position.e_relative_pos(previous_pos), 2.2)
Exemplo n.º 6
0
    def test_g21(self):
        # no parameters
        gcode = "G21"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G21")
        self.assertDictEqual({}, parsed.parameters)

        # with parameters (bogus)
        gcode = "G21X100fdafdsa; Here is a comment"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G21")
        self.assertDictEqual({}, parsed.parameters)
Exemplo n.º 7
0
    def test_g20(self):
        # no parameters
        gcode = "G20"
        cmd, parameters = Commands.parse(gcode)
        self.assertEqual(cmd, "G20")
        self.assertDictEqual({}, parameters)

        # with parameters (bogus)
        gcode = "G20X100fdafdsa; Here is a comment"
        cmd, parameters = Commands.parse(gcode)
        self.assertEqual(cmd, "G20")
        self.assertDictEqual({}, parameters)
Exemplo n.º 8
0
    def test_reset(self):
        """Test init state."""
        position = Position(self.Settings, self.OctoprintPrinterProfile, False)
        # reset all initialized vars to something else
        position.update(Commands.parse("G28"))
        position.update(Commands.parse("G0 X1 Y1 Z1"))

        # reset
        position = Position(self.Settings, self.OctoprintPrinterProfile, False)

        # test initial state
        self.assertEqual(len(position.Positions), 0)
        self.assertIsNone(position.SavedPosition)
Exemplo n.º 9
0
 def test_IsAtCurrentPosition(self):
     # Received: x:119.91,y:113.34,z:2.1,e:0.0, Expected:
     # x:119.9145519,y:113.33847,z:2.1
     # G1 X119.915 Y113.338 F7200
     position = Position(self.Settings, self.OctoprintPrinterProfile, False)
     position.Printer.printer_position_confirmation_tolerance = .0051
     position.update(Commands.parse("M83"))
     position.update(Commands.parse("G90"))
     position.update(Commands.parse("G28"))
     position.update(Commands.parse("G1 X119.915 Y113.338 Z2.1 F7200"))
     self.assertTrue(position.is_at_current_position(119.91, 113.34, 2.1))
     position.update(Commands.parse("g0 x120 y121 z2.1"))
     self.assertTrue(position.is_at_previous_position(119.91, 113.34, 2.1))
Exemplo n.º 10
0
    def test_parameter_repetition(self):
        # test parameter repetition
        gcode = "g28 xxz"
        parsed = Commands.parse(gcode)
        self.assertIsNone(parsed.cmd)
        self.assertIsNotNone(parsed.error)
        self.assertNotEqual(len(parsed.error), 0)

        # test parameter repetition wrapped in comments
        gcode = "(comment in the front)g(comment in middle)2()8x(another comment in middle)x(comment between" \
                " address and value)100()1 . 1(another); Here is a comment"
        parsed = Commands.parse(gcode)
        self.assertIsNone(parsed.cmd)
        self.assertIsNotNone(parsed.error)
        self.assertNotEqual(len(parsed.error), 0)
Exemplo n.º 11
0
 def test_multiple_signs_parameter(self):
     # test multiple signs in parameter 1
     gcode = "(comment in the front)g(comment in middle)2()8(another comment in middle)x(comment between" \
             " address and value)+100()1 . 1+(another); Here is a comment"
     parsed = Commands.parse(gcode)
     self.assertIsNone(parsed.cmd)
     self.assertIsNotNone(parsed.error)
     self.assertNotEqual(len(parsed.error), 0)
     # test multiple signs in parameter 2
     gcode = "(comment in the front)g(comment in middle)2()8x(another comment in middle)x(comment between" \
             " address and value)++100()1 . 1(another); Here is a comment"
     parsed = Commands.parse(gcode)
     self.assertIsNone(parsed.cmd)
     self.assertIsNotNone(parsed.error)
     self.assertNotEqual(len(parsed.error), 0)
Exemplo n.º 12
0
    def test_parameter_repetition(self):
        # test parameter repetition
        gcode = "g28 xxz"
        with self.assertRaises(Exception) as context:
            Commands.parse(gcode)
        self.assertTrue('A parameter value was repeated, cannot parse gcode.'
                        in context.exception)

        # test parameter repetition wrapped in comments
        gcode = "(comment in the front)g(comment in middle)2()8x(another comment in middle)x(comment between" \
                " address and value)100()1 . 1(another); Here is a comment"
        with self.assertRaises(Exception) as context:
            Commands.parse(gcode)
        self.assertTrue('A parameter value was repeated, cannot parse gcode.'
                        in context.exception)
Exemplo n.º 13
0
    def test_m105(self):
        gcode = "m105;"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "M105")
        self.assertDictEqual(parsed.parameters, {})

        gcode = "m105X1;"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "M105")
        self.assertDictEqual(parsed.parameters, {})

        gcode = "m105fdsafdsafdsfsdfsd;"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "M105")
        self.assertDictEqual(parsed.parameters, {})
Exemplo n.º 14
0
 def test_parse_int_negative(self):
     # test negative F error
     gcode = "G00 F- 1 09 "
     parsed = Commands.parse(gcode)
     self.assertIsNone(parsed.cmd)
     self.assertIsNotNone(parsed.error)
     self.assertNotEqual(len(parsed.error), 0)
Exemplo n.º 15
0
 def test_multiple_decimals_command(self):
     # test multiple decimal points in parameter 2
     gcode = "G28.0."
     parsed = Commands.parse(gcode)
     self.assertIsNone(parsed.cmd)
     self.assertIsNotNone(parsed.error)
     self.assertNotEqual(len(parsed.error), 0)
Exemplo n.º 16
0
    def __init__(self, octolapse_settings, octoprint_printer_profile):
        self.Commands = Commands()
        self.Settings = octolapse_settings  # type: OctolapseSettings
        self.StabilizationPaths = self.Settings.current_stabilization(
        ).get_stabilization_paths()
        self.Snapshot = Snapshot(self.Settings.current_snapshot())
        self.Printer = Printer(self.Settings.current_printer())
        self.OctoprintPrinterProfile = octoprint_printer_profile
        self.BoundingBox = utility.get_bounding_box(self.Printer,
                                                    octoprint_printer_profile)
        self.IsTestMode = self.Settings.current_debug_profile().is_test_mode

        self.RetractedBySnapshotStartGcode = None
        self.ZhopBySnapshotStartGcode = None
        self.IsRelativeOriginal = None
        self.IsRelativeCurrent = None
        self.IsMetricOriginal = None
        self.IsMetricCurrent = None
        self.IsExtruderRelativeOriginal = None
        self.IsExtruderRelativeCurrent = None
        self.FOriginal = None
        self.FCurrent = None
        self.HasSnapshotPositionErrors = False
        self.SnapshotPositionErrors = ""
        self.ZLift = 0
        self.RetractedLength = 0
        self.AxisSpeedUnits = self.Printer.axis_speed_display_units
        self.ReturnWhenComplete = True
        if self.AxisSpeedUnits not in ["mm-min", "mm-sec"]:
            self.AxisSpeedUnits = "mm-min"

        self.RetractSpeed = self.convert_to_mm_min(self.Printer.retract_speed)
        self.DetractSpeed = self.convert_to_mm_min(self.Printer.detract_speed)
        self.TravelSpeed = self.convert_to_mm_min(self.Printer.movement_speed)
        self.ZHopSpeed = self.convert_to_mm_min(self.Printer.z_hop_speed)
Exemplo n.º 17
0
    def test_multiple_decimals_parameter(self):
        # test multiple decimal points in parameter 1
        gcode = "(comment in the front)g(comment in middle)2()8x(another comment in middle)x(comment between" \
                "address and value)+100()1 . 1(another).; Here is a comment"
        with self.assertRaises(Exception) as context:
            Commands.parse(gcode)
        self.assertTrue(
            "Could not parse float from parameter string, saw multiple decimal points."
            in context.exception)

        # test multiple decimal points in parameter 2
        gcode = "(comment in the front)g(comment in middle)2()8x(another comment in middle)x(comment between" \
                " address and value)1.00()1 . 1(another); Here is a comment"
        with self.assertRaises(Exception) as context:
            Commands.parse(gcode)
        self.assertTrue(
            "Could not parse float from parameter string, saw multiple decimal points."
            in context.exception)
Exemplo n.º 18
0
    def test_g0(self):

        # no parameters
        gcode = "g0"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G0")
        self.assertDictEqual({}, parsed.parameters)

        # no parameters, double 0
        gcode = "g00"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G0")
        self.assertDictEqual({}, parsed.parameters)

        # all parameters with comment
        gcode = "g0 x100 y200.0 z3.0001 e1.1 f7200.000; Here is a comment"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G0")
        self.assertEqual(parsed.parameters["X"], 100)
        self.assertEqual(parsed.parameters["Y"], 200.0)
        self.assertEqual(parsed.parameters["Z"], 3.0001)
        self.assertEqual(parsed.parameters["E"], 1.1)
        self.assertEqual(parsed.parameters["F"], 7200.000)

        # all parameters, no spaces
        gcode = "g0x100y200.0z3.0001e1.1f7200.000"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G0")
        self.assertEqual(parsed.parameters["X"], 100)
        self.assertEqual(parsed.parameters["Y"], 200.0)
        self.assertEqual(parsed.parameters["Z"], 3.0001)
        self.assertEqual(parsed.parameters["E"], 1.1)
        self.assertEqual(parsed.parameters["F"], 7200.000)

        # all parameters, funky spaces
        gcode = "g  0 x  10 0  y2 00 .0z  3.0 001 e1. 1 f72 00 .000 "
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G0")
        self.assertEqual(parsed.parameters["X"], 100)
        self.assertEqual(parsed.parameters["Y"], 200.0)
        self.assertEqual(parsed.parameters["Z"], 3.0001)
        self.assertEqual(parsed.parameters["E"], 1.1)
        self.assertEqual(parsed.parameters["F"], 7200.000)
Exemplo n.º 19
0
    def test_G90InfluencesExtruder_UpdatePosition(self):
        """Test G90 for machines where it influences the coordinate system of the extruder."""
        position = Position(self.Settings, self.OctoprintPrinterProfile, True)
        # Make sure the axis is homed
        position.update(Commands.parse("G28"))
        # set absolute mode with G90
        position.update(Commands.parse("g90"))
        # update the position to 10 (absolute)
        position.update_position(e=10)
        self.assertEqual(position.e(), 10)
        # update the position to 10 again (absolute) to make sure we are in absolute
        # coordinates.
        position.update_position(e=10)
        self.assertEqual(position.e(), 10)

        # set relative mode with G90
        position.update(Commands.parse("g91"))
        # update the position to 20 (relative)
        position.update_position(e=20)
        self.assertEqual(position.e(), 30)
Exemplo n.º 20
0
    def test_G92AbsoluteMovement(self):
        """Test the G92 command, move in absolute mode and test results."""
        position = Position(self.Settings, self.OctoprintPrinterProfile, False)

        # set homed axis, absolute coordinates, and set position
        position.update(Commands.parse("G28"))
        position.update(Commands.parse("G90"))
        position.update(Commands.parse("G1 x100 y200 z150"))
        position.update(Commands.parse("G92 x10 y20 z30"))
        self.assertEqual(position.x(), 100)
        self.assertEqual(position.x_offset(), 90)
        self.assertEqual(position.y(), 200)
        self.assertEqual(position.y_offset(), 180)
        self.assertEqual(position.z(), 150)
        self.assertEqual(position.z_offset(), 120)

        # move to origin
        position.update(Commands.parse("G1 x-90 y-180 z-120"))
        self.assertEqual(position.x(), 0)
        self.assertEqual(position.x_offset(), 90)
        self.assertEqual(position.y(), 0)
        self.assertEqual(position.y_offset(), 180)
        self.assertEqual(position.z(), 0)
        self.assertEqual(position.z_offset(), 120)

        # move back
        position.update(Commands.parse("G1 x0 y0 z0"))
        self.assertEqual(position.x(), 90)
        self.assertEqual(position.x_offset(), 90)
        self.assertEqual(position.y(), 180)
        self.assertEqual(position.y_offset(), 180)
        self.assertEqual(position.z(), 120)
        self.assertEqual(position.z_offset(), 120)
Exemplo n.º 21
0
    def test_G92SetPosition(self):
        """Test the G92 command, settings the position."""
        position = Position(self.Settings, self.OctoprintPrinterProfile, False)
        # no homed axis
        position.update(Commands.parse("G92 x10 y20 z30"))
        self.assertEqual(position.x(), 10)
        self.assertEqual(position.y(), 20)
        self.assertEqual(position.z(), 30)
        self.assertFalse(position.has_homed_axes())

        # set homed axis, absolute coordinates, and set position
        position.update(Commands.parse("G28"))
        position.update(Commands.parse("G90"))
        position.update(Commands.parse("G1 x100 y200 z150"))
        position.update(Commands.parse("G92 x10 y20 z30"))
        self.assertEqual(position.x(), 100)
        self.assertEqual(position.x_offset(), 90)
        self.assertEqual(position.y(), 200)
        self.assertEqual(position.y_offset(), 180)
        self.assertEqual(position.z(), 150)
        self.assertEqual(position.z_offset(), 120)

        # Move to same position and retest
        position.update(Commands.parse("G1 x0 y0 z0"))
        self.assertEqual(position.x(), 90)
        self.assertEqual(position.x_offset(), 90)
        self.assertEqual(position.y(), 180)
        self.assertEqual(position.y_offset(), 180)
        self.assertEqual(position.z(), 120)
        self.assertEqual(position.z_offset(), 120)

        # Move and retest
        position.update(Commands.parse("G1 x-10 y10 z20"))
        self.assertEqual(position.x(), 80)
        self.assertEqual(position.x_offset(), 90)
        self.assertEqual(position.y(), 190)
        self.assertEqual(position.y_offset(), 180)
        self.assertEqual(position.z(), 140)
        self.assertEqual(position.z_offset(), 120)

        # G92 with no parameters
        position.update(Commands.parse("G92"))
        self.assertEqual(position.x(), 80)
        self.assertEqual(position.x_offset(), 80)
        self.assertEqual(position.y(), 190)
        self.assertEqual(position.y_offset(), 190)
        self.assertEqual(position.z(), 140)
        self.assertEqual(position.z_offset(), 140)
Exemplo n.º 22
0
    def test_GetSnapshotGcode_Fixed_AbsoluteCoordintes_ExtruderRelative(self):
        """Test snapshot gcode in absolute coordinate system with relative extruder and fixed coordinate
        stabilization """
        # adjust the settings for absolute position and create the snapshot gcode generator
        self.Settings.current_stabilization().x_type = "fixed_coordinate"
        self.Settings.current_stabilization().x_fixed_coordinate = 10
        self.Settings.current_stabilization().y_type = "fixed_coordinate"
        self.Settings.current_stabilization().y_fixed_coordinate = 20
        snapshot_gcode_generator = SnapshotGcodeGenerator(
            self.Settings, self.create_octoprint_printer_profile())
        self.Extruder.is_retracted = lambda: True

        self.Position.update(Commands.parse("G90"))
        self.Position.update(Commands.parse("M83"))
        self.Position.update(Commands.parse("G28"))
        self.Position.update(Commands.parse("G0 X95 Y95 Z0.2 F3600"))
        parsed_command = Commands.parse("G0 X100 Y100")
        self.Position.update(parsed_command)
        snapshot_gcode = snapshot_gcode_generator.create_snapshot_gcode(
            self.Position, None, parsed_command)
        gcode_commands = snapshot_gcode.snapshot_gcode()

        # verify the created gcodegcode_commands
        self.assertEqual(gcode_commands[0], "G1 E-4.00000 F4800")
        self.assertEqual(gcode_commands[1], "G1 X10.000 Y20.000 F10800")
        self.assertEqual(gcode_commands[2], "G1 X100.000 Y100.000")
        self.assertEqual(gcode_commands[3], "G1 E4.00000 F3000")
        self.assertEqual(gcode_commands[4], "G1 F3600")
        self.assertEqual(gcode_commands[5], parsed_command.gcode)

        # verify the return coordinates
        self.assertEqual(snapshot_gcode.ReturnX, 100)
        self.assertEqual(snapshot_gcode.ReturnY, 100)
        self.assertEqual(snapshot_gcode.ReturnZ, 0.2)

        self.assertEqual(snapshot_gcode.X, 10)
        self.assertEqual(snapshot_gcode.Y, 20)
        self.assertEqual(snapshot_gcode.Z, None)
Exemplo n.º 23
0
    def setUp(self):
        self.Commands = Commands()
        self.Settings = OctolapseSettings(NamedTemporaryFile().name)
        # in the general test case we want auto_detect_position to be false
        # else we'll have to simulate a position update (m114 return) after
        # a home (g28) command
        self.Settings.current_printer().auto_detect_position = False
        # since we've set auto_detect_position to false, we need to set
        # an origin, else X,Y and Z will still be None after a home command
        self.Settings.current_printer().origin_x = 0
        self.Settings.current_printer().origin_y = 0
        self.Settings.current_printer().origin_z = 0

        self.OctoprintPrinterProfile = self.create_octolapse_printer_profile()
Exemplo n.º 24
0
    def test_g1(self):
        # no parameters
        gcode = "g1"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G1")
        self.assertDictEqual({}, parsed.parameters)

        # no parameters, double 0
        gcode = "g01"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G1")
        self.assertDictEqual({}, parsed.parameters)

        # all parameters with comment
        gcode = "g1 x100 y200.0 z3.0001 e1.1 f7200.000; Here is a comment"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G1")
        self.assertEqual(parsed.parameters["X"], 100)
        self.assertEqual(parsed.parameters["Y"], 200.0)
        self.assertEqual(parsed.parameters["Z"], 3.0001)
        self.assertEqual(parsed.parameters["E"], 1.1)
        self.assertEqual(parsed.parameters["F"], 7200.000)

        # all parameters, no spaces
        gcode = "g1x100y200.0z3.0001e1.1f7200.000"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G1")
        self.assertEqual(parsed.parameters["X"], 100)
        self.assertEqual(parsed.parameters["Y"], 200.0)
        self.assertEqual(parsed.parameters["Z"], 3.0001)
        self.assertEqual(parsed.parameters["E"], 1.1)
        self.assertEqual(parsed.parameters["F"], 7200.000)

        # all parameters, funky spaces
        gcode = "g  01 x  10 0  y2 00 .0z  3.0 001 e1. 1 f72 00 .000 "
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G1")
        self.assertEqual(parsed.parameters["X"], 100)
        self.assertEqual(parsed.parameters["Y"], 200.0)
        self.assertEqual(parsed.parameters["Z"], 3.0001)
        self.assertEqual(parsed.parameters["E"], 1.1)
        self.assertEqual(parsed.parameters["F"], 7200.000)

        # from issue 86
        gcode = "G1 X -18 Y95 F1000"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G1")
        self.assertEqual(parsed.parameters["X"], -18)
        self.assertEqual(parsed.parameters["Y"], 95)
        self.assertNotIn("Z", parsed.parameters)
        self.assertNotIn("E", parsed.parameters)
        self.assertEqual(parsed.parameters["F"], 1000)
Exemplo n.º 25
0
class SnapshotGcode(object):
    CommandsDictionary = Commands()
    START_GCODE = 'start-gcode'
    SNAPSHOT_COMMANDS = 'snapshot-commands'
    RETURN_COMMANDS = 'return-commands'
    END_GCODE = 'end-gcode'

    def __init__(self):

        self.StartGcode = []
        self.SnapshotCommands = []
        self.ReturnCommands = []
        self.EndGcode = []
        self.X = None
        self.ReturnX = None
        self.Y = None
        self.ReturnY = None
        self.Z = None
        self.ReturnZ = None
        self.SnapshotIndex = -1

    def snapshot_gcode(self):
        return self.StartGcode + self.SnapshotCommands + self.ReturnCommands + self.EndGcode

    def append(self, command_type, command):
        if command_type == self.START_GCODE:
            self.StartGcode.append(command)
        elif command_type == self.SNAPSHOT_COMMANDS:
            self.SnapshotCommands.append(command)
        elif command_type == self.RETURN_COMMANDS:
            self.ReturnCommands.append(command)
        elif command_type == self.END_GCODE:
            self.EndGcode.append(command)

    def end_index(self):
        return len(self.StartGcode) + len(self.SnapshotCommands) + len(
            self.ReturnCommands) + len(self.EndGcode) - 1

    def snapshot_index(self):
        return len(self.StartGcode) + len(self.SnapshotCommands) - 1
Exemplo n.º 26
0
    def test_G92RelativeMovement(self):
        """Test the G92 command, move in relative mode and test results."""
        position = Position(self.Settings, self.OctoprintPrinterProfile, False)

        # set homed axis, relative coordinates, and set position
        position.update(Commands.parse("G28"))
        position.update(Commands.parse("G91"))
        position.update(Commands.parse("G1 x100 y200 z150"))
        position.update(Commands.parse("G92 x10 y20 z30"))
        self.assertEqual(position.x(), 100)
        self.assertEqual(position.x_offset(), 90)
        self.assertEqual(position.y(), 200)
        self.assertEqual(position.y_offset(), 180)
        self.assertEqual(position.z(), 150)
        self.assertEqual(position.z_offset(), 120)

        # move to origin
        position.update(Commands.parse("G1 x-100 y-200 z-150"))
        self.assertEqual(position.x(), 0)
        self.assertEqual(position.x_offset(), 90)
        self.assertEqual(position.y(), 0)
        self.assertEqual(position.y_offset(), 180)
        self.assertEqual(position.z(), 0)
        self.assertEqual(position.z_offset(), 120)

        # advance each axis
        position.update(Commands.parse("G1 x1 y2 z3"))
        self.assertEqual(position.x(), 1)
        self.assertEqual(position.x_offset(), 90)
        self.assertEqual(position.y(), 2)
        self.assertEqual(position.y_offset(), 180)
        self.assertEqual(position.z(), 3)
        self.assertEqual(position.z_offset(), 120)

        # advance again
        position.update(Commands.parse("G1 x1 y2 z3"))
        self.assertEqual(position.x(), 2)
        self.assertEqual(position.x_offset(), 90)
        self.assertEqual(position.y(), 4)
        self.assertEqual(position.y_offset(), 180)
        self.assertEqual(position.z(), 6)
        self.assertEqual(position.z_offset(), 120)
Exemplo n.º 27
0
    def test_UpdatePosition_force(self):
        """Test the UpdatePosition function with the force option set to true."""
        position = Position(self.Settings, self.OctoprintPrinterProfile, False)
        position.update(Commands.parse("G28"))
        position.update_position(x=0, y=0, z=0, e=0, force=True)

        self.assertEqual(position.x(), 0)
        self.assertEqual(position.y(), 0)
        self.assertEqual(position.z(), 0)
        self.assertEqual(position.e(), 0)

        position.update_position(x=1, y=2, z=3, e=4, force=True)
        self.assertEqual(position.x(), 1)
        self.assertEqual(position.y(), 2)
        self.assertEqual(position.z(), 3)
        self.assertEqual(position.e(), 4)

        position.update_position(x=None, y=None, z=None, e=None, force=True)
        self.assertEqual(position.x(), 1)
        self.assertEqual(position.y(), 2)
        self.assertEqual(position.z(), 3)
        self.assertEqual(position.e(), 4)
Exemplo n.º 28
0
    def test_inline_comments(self):
        gcode = "g28(this is an inline commentx)yz; Here is a comment"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G28")
        self.assertFalse("X" in parsed.parameters)
        self.assertIsNone(parsed.parameters["Y"])
        self.assertIsNone(parsed.parameters["Z"])

        gcode = "g28(this is an inline commentx); Here is a comment"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G28")
        self.assertFalse("X" in parsed.parameters)
        self.assertFalse("Y" in parsed.parameters)
        self.assertFalse("Z" in parsed.parameters)

        gcode = "(comment in the front)g28; Here is a comment"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G28")
        self.assertFalse("X" in parsed.parameters)
        self.assertFalse("Y" in parsed.parameters)
        self.assertFalse("Z" in parsed.parameters)

        gcode = "(comment in the front)g28(comment in back); Here is a comment"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G28")
        self.assertFalse("X" in parsed.parameters)
        self.assertFalse("Y" in parsed.parameters)
        self.assertFalse("Z" in parsed.parameters)

        gcode = "(comment in the front)g(comment in middle)28(comment in back); Here is a comment"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G28")
        self.assertFalse("X" in parsed.parameters)
        self.assertFalse("Y" in parsed.parameters)
        self.assertFalse("Z" in parsed.parameters)

        gcode = "(comment in the front)g(comment in middle)2()8(another comment in middle)x(comment between" \
                "address and value)100()1 . 1(another); Here is a comment"
        parsed = Commands.parse(gcode)
        self.assertEqual(parsed.cmd, "G28")
        self.assertEqual(parsed.parameters["X"], 1001.1)
        self.assertFalse("Y" in parsed.parameters)
        self.assertFalse("Z" in parsed.parameters)
Exemplo n.º 29
0
    def on_gcode_queuing(self, command_string, cmd_type, gcode, tags):

        self.detect_timelapse_start(command_string, tags)

        # if the timelapse is not active, exit without changing any gcode
        if not self.is_timelapse_active():
            return

        self.check_current_line_number(tags)

        # update the position tracker so that we know where all of the axis are.
        # We will need this later when generating snapshot gcode so that we can return to the previous
        # position
        is_snapshot_gcode_command = self._is_snapshot_command(command_string)

        try:
            self.Settings.current_debug_profile().log_gcode_queuing(
                "Queuing Command: Command Type:{0}, gcode:{1}, cmd: {2}, tags: {3}".format(
                    cmd_type, gcode, command_string, tags
                )
            )

            try:
                cmd, parameters = Commands.parse(command_string)
            except ValueError as e:
                message = "An error was thrown by the gcode parser, stopping timelapse.  Details: {0}".format(e.message)
                self.Settings.current_debug_profile().log_warning(
                    message
                )
                self.stop_snapshots(message, True)
                return None

            # get the position state in case it has changed
            # if there has been a position or extruder state change, inform any listener

            if cmd is not None and not is_snapshot_gcode_command:
                # create our state change dictionaries
                self.Position.update(command_string, cmd, parameters)

            # if this code is snapshot gcode, simply return it to the printer.
            if {'plugin:octolapse', 'snapshot_gcode'}.issubset(tags):
                return None

            if not self.check_for_non_metric_errors():
                if self.Position.has_position_error(0):
                    # There are position errors, report them!
                    self._on_position_error()
                elif (self.State == TimelapseState.WaitingForTrigger
                        and (self.Position.requires_location_detection(1)) and self.OctoprintPrinter.is_printing()):

                    self.State = TimelapseState.AcquiringLocation

                    if self.OctoprintPrinter.set_job_on_hold(True):
                        thread = threading.Thread(target=self.acquire_position, args=[command_string, cmd, parameters])
                        thread.daemon = True
                        thread.start()
                        return None,
                elif (self.State == TimelapseState.WaitingForTrigger
                      and self.OctoprintPrinter.is_printing()
                      and not self.Position.has_position_error(0)):
                    # update the triggers with the current position
                    self.Triggers.update(self.Position, command_string)
                    # see if at least one trigger is triggering
                    _first_triggering = self.get_first_triggering()

                    if _first_triggering:
                        # We are triggering, take a snapshot
                        self.State = TimelapseState.TakingSnapshot
                        # pause any timer triggers that are enabled
                        self.Triggers.pause()

                        # get the job lock
                        if self.OctoprintPrinter.set_job_on_hold(True):
                            # take the snapshot on a new thread
                            thread = threading.Thread(
                                target=self.acquire_snapshot, args=[command_string, cmd, parameters, _first_triggering]
                            )
                            thread.daemon = True
                            thread.start()
                            # suppress the current command, we'll send it later
                            return None,

                elif self.State == TimelapseState.TakingSnapshot:
                    # Don't do anything further to any commands unless we are
                    # taking a timelapse , or if octolapse paused the print.
                    # suppress any commands we don't, under any cirumstances,
                    # to execute while we're taking a snapshot

                    if cmd in self.Commands.SuppressedSnapshotGcodeCommands:
                        command_string = None,  # suppress the command

            if is_snapshot_gcode_command:
                # in all cases do not return the snapshot command to the printer.
                # It is NOT a real gcode and could cause errors.
                command_string = None,

        except Exception as e:
            self.Settings.current_debug_profile().log_exception(e)
            raise

        # notify any callbacks
        self._send_state_changed_message()

        # do any post processing for test mode
        if command_string != (None,):
            command_string = self._get_command_for_octoprint(command_string, cmd,parameters)
        return command_string
Exemplo n.º 30
0
    def __init__(
            self, settings, octoprint_printer, data_folder, timelapse_folder,
            on_print_started=None, on_print_start_failed=None,
            on_snapshot_start=None, on_snapshot_end=None,
            on_render_start=None, on_render_end=None,
            on_timelapse_stopping=None, on_timelapse_stopped=None,
            on_state_changed=None, on_timelapse_start=None, on_timelapse_end = None,
            on_snapshot_position_error=None, on_position_error=None):
        # config variables - These don't change even after a reset
        self.DataFolder = data_folder
        self.Settings = settings  # type: OctolapseSettings
        self.OctoprintPrinter = octoprint_printer
        self.DefaultTimelapseDirectory = timelapse_folder
        self.OnPrintStartCallback = on_print_started
        self.OnPrintStartFailedCallback = on_print_start_failed
        self.OnRenderStartCallback = on_render_start
        self.OnRenderEndCallback = on_render_end
        self.OnSnapshotStartCallback = on_snapshot_start
        self.OnSnapshotCompleteCallback = on_snapshot_end
        self.TimelapseStoppingCallback = on_timelapse_stopping
        self.TimelapseStoppedCallback = on_timelapse_stopped
        self.OnStateChangedCallback = on_state_changed
        self.OnTimelapseStartCallback = on_timelapse_start
        self.OnTimelapseEndCallback = on_timelapse_end
        self.OnSnapshotPositionErrorCallback = on_snapshot_position_error
        self.OnPositionErrorCallback = on_position_error
        self.Commands = Commands()  # used to parse and generate gcode
        self.Triggers = None
        self.PrintEndStatus = "Unknown"
        self.LastStateChangeMessageTime = None
        self.StateChangeMessageThread = None
        # Settings that may be different after StartTimelapse is called

        self.OctoprintPrinterProfile = None
        self.PrintStartTime = None
        self.FfMpegPath = None
        self.Snapshot = None
        self.Gcode = None
        self.Printer = None
        self.CaptureSnapshot = None
        self.Position = None
        self.Rendering = None
        self.State = TimelapseState.Idle
        self.IsTestMode = False
        # State Tracking that should only be reset when starting a timelapse
        self.SnapshotCount = 0

        self.HasBeenStopped = False
        self.TimelapseStopRequested = False
        self.SavedCommand = None
        self.SecondsAddedByOctolapse = 0
        # State tracking variables
        self.RequiresLocationDetectionAfterHome = False

        # fetch position private variables
        self._position_payload = None
        self._position_timeout_long = 600.0
        self._position_timeout_short = 10.0
        self._position_signal = threading.Event()
        self._position_signal.set()

        # get snapshot async private variables
        self._snapshot_success = False
        # It shouldn't take more than 5 seconds to take a snapshot!
        self._snapshot_timeout = 5.0
        self._snapshot_signal = threading.Event()
        self._snapshot_signal.set()
        self._most_recent_snapshot_payload = None

        self.CurrentProfiles = {}
        self.CurrentFileLine = 0

        # snapshot thread queue
        self._snapshot_task_queue = Queue(maxsize=1)
        self._rendering_task_queue = Queue(maxsize=1)
        self._reset()