def setUp(self): self.Settings = OctolapseSettings(NamedTemporaryFile().name) self.Settings.current_printer().auto_detect_position = False 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_octoprint_printer_profile()
def setUp(self): self.Settings = OctolapseSettings(NamedTemporaryFile().name) self.OctoprintPrinterProfile = self.create_octoprint_printer_profile() printer = get_printer_profile() self.Settings.printers.update({printer["guid"]: Printer(printer=printer)}) self.Settings.current_printer_profile_guid = printer["guid"] self.Extruder = Extruder(self.Settings) self.Position = Position(self.Settings, self.OctoprintPrinterProfile, False)
def setUp(self): self.Settings = OctolapseSettings(NamedTemporaryFile().name) self.Settings.current_printer().e_axis_default_mode = 'relative' self.Settings.current_printer().xyz_axes_default_mode = 'absolute' self.Settings.current_printer().auto_detect_position = False 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_octoprint_printer_profile()
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()
def migrate_pre_0_3_3_rc3_dev(current_version, settings_dict, log_file_path, default_settings_path): # versions prior to or equal to 0.3.3rc3.dev0 need to have the snapshot profiles reset to the defaults # get the default settings new_settings = OctolapseSettings( log_file_path, get_default_settings(default_settings_path), current_version) # remove the existing renderings settings_dict["snapshots"] = [] for key, snapshot in new_settings.snapshots.items(): settings_dict["snapshots"].append(snapshot.to_dict()) # set the default snapshot profile guid so that it is selected by default settings_dict[ "current_snapshot_profile_guid"] = new_settings.current_snapshot_profile_guid # migrate the camera settings so that if there is no enabled column if (len(settings_dict["cameras"]) > 0 and "enabled" not in settings_dict["cameras"][0]): # we need to migrate the cameras and enable only the current camera for camera in settings_dict["cameras"]: if camera["guid"] == settings_dict["current_camera_profile_guid"]: camera["enabled"] = True else: camera["enabled"] = False # update the version settings_dict["version"] = current_version # return the dict return settings_dict
def setUp(self): new_settings, defaults_loaded = OctolapseSettings.load( "C:\\Users\\Brad\\AppData\\Roaming\\OctoPrint\\data\\octolapse\\settings.json", "0.4.0rc1.dev0", "C:\\Users\\Brad\\AppData\\Roaming\\OctoPrint\\data\\octolapse\\", "settings.json") self.Commands = Commands() self.Settings = new_settings self.Printer = self.Settings.profiles.current_printer() self.Stabilization = self.Settings.profiles.current_stabilization() self.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.Printer.home_x = 0 self.Printer.home_y = 0 self.Printer.home_z = 0 assert (isinstance(self.Printer, PrinterProfile)) self.Printer.slicer_type = SlicerSettings.SlicerTypeSlic3rPe slicer_settings = self.Printer.get_current_slicer_settings() assert (isinstance(slicer_settings, Slic3rPeSettings)) slicer_settings.retract_length = 0.8 slicer_settings.retract_speed = 2400 / 60 self.OctoprintPrinterProfile = self.create_octolapse_printer_profile()
def setUp(self): self.octolapse_settings = OctolapseSettings(NamedTemporaryFile().name) self.rendering_job_id = "job_id" self.print_name = "print_name" self.print_start_time = 0 self.print_end_time = 100 # Create fake snapshots. self.capture_template = get_snapshot_filename(self.print_name, SnapshotNumberFormat) self.data_directory = mkdtemp() self.octoprint_timelapse_folder = mkdtemp() self.ffmpeg_path = "ffmpeg" self.render_task_queue = Queue(maxsize=1) self.render_task_queue.put(self.rendering_job_id)
class Test_Position(unittest.TestCase): def setUp(self): self.Commands = Commands() self.Settings = OctolapseSettings("c:\\temp\\octolapse.log") self.OctoprintPrinterProfile = self.CreateOctoprintPrinterProfile() def tearDown(self): del self.Commands del self.Settings def CreateOctoprintPrinterProfile(self): return { "volume": { "custom_box": False, "width": 250, "depth": 200, "height": 200 } } def test_PositionError(self): """Test the IsInBounds function to make sure the program will not attempt to operate after being told to move out of bounds.""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) # Initial test, should return false without any coordinates self.assertTrue(not position.HasPositionError) self.assertTrue(position.PositionError is None) # home the axis and test position.Update("G28") self.assertTrue(not position.HasPositionError) self.assertTrue(position.PositionError is None) #X axis tests # reset, home the axis and test again position.Reset() position.Update("G28") self.assertTrue(not position.HasPositionError) self.assertTrue(position.PositionError is None) # move out of bounds min position.Update("G0 x-0.0001") self.assertTrue(position.HasPositionError) self.assertTrue(position.PositionError is not None) # move back in bounds position.Update("G0 x0.0") self.assertTrue(not position.HasPositionError) self.assertTrue(position.PositionError is None) # move to middle position.Update("G0 x125") self.assertTrue(not position.HasPositionError) self.assertTrue(position.PositionError is None) # move to max position.Update("G0 x250") self.assertTrue(not position.HasPositionError) self.assertTrue(position.PositionError is None) # move out of bounds max position.Update("G0 x250.0001") self.assertTrue(position.HasPositionError) self.assertTrue(position.PositionError is not None) #Y axis tests # reset, home the axis and test again position.Reset() position.Update("G28") self.assertTrue(not position.HasPositionError) self.assertTrue(position.PositionError is None) # move out of bounds min position.Update("G0 y-0.0001") self.assertTrue(position.HasPositionError) self.assertTrue(position.PositionError is not None) # move back in bounds position.Update("G0 y0.0") self.assertTrue(not position.HasPositionError) self.assertTrue(position.PositionError is None) # move to middle position.Update("G0 y100") self.assertTrue(not position.HasPositionError) self.assertTrue(position.PositionError is None) # move to max position.Update("G0 y200") self.assertTrue(not position.HasPositionError) self.assertTrue(position.PositionError is None) # move out of bounds max position.Update("G0 y200.0001") self.assertTrue(position.HasPositionError) self.assertTrue(position.PositionError is not None) #Z axis tests # reset, home the axis and test again position.Reset() position.Update("G28") self.assertTrue(not position.HasPositionError) self.assertTrue(position.PositionError is None) # move out of bounds min position.Update("G0 z-0.0001") self.assertTrue(position.HasPositionError) self.assertTrue(position.PositionError is not None) # move back in bounds position.Update("G0 z0.0") self.assertTrue(not position.HasPositionError) self.assertTrue(position.PositionError is None) # move to middle position.Update("G0 z100") self.assertTrue(not position.HasPositionError) self.assertTrue(position.PositionError is None) # move to max position.Update("G0 z200") self.assertTrue(not position.HasPositionError) self.assertTrue(position.PositionError is None) # move out of bounds max position.Update("G0 z200.0001") self.assertTrue(position.HasPositionError) self.assertTrue(position.PositionError is not None) def test_reset(self): """Test init state.""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) # reset all initialized vars to something else position.X = -1 position.XOffset = -1 position.XPrevious = -1 position.Y = -1 position.YOffset = -1 position.YPrevious = -1 position.Z = -1 position.ZOffset = -1 position.ZPrevious = -1 position.E = -1 position.EOffset = -1 position.EPrevious = -1 position.IsRelative = True position.IsExtruderRelative = False position.Height = -1 position.HeightPrevious = -1 position.ZDelta = -1 position.ZDeltaPrevious = -1 position.Layer = -1 position.IsLayerChange = True position.IsZHop = True position.XHomed = True position.YHomed = True position.ZHomed = True position.HasPositionError = True position.IsZHop = True position.PositionError = "Error!" # reset position.Reset() # test initial state self.assertTrue(position.X is None) self.assertTrue(position.XOffset == 0) self.assertTrue(position.XPrevious is None) self.assertTrue(position.Y is None) self.assertTrue(position.YOffset == 0) self.assertTrue(position.YPrevious is None) self.assertTrue(position.Z is None) self.assertTrue(position.ZOffset == 0) self.assertTrue(position.ZPrevious is None) self.assertTrue(position.E == 0) self.assertTrue(position.EOffset == 0) self.assertTrue(position.EPrevious == 0) self.assertTrue(position.IsRelative == False) self.assertTrue(position.IsExtruderRelative) self.assertTrue(position.Height is None) self.assertTrue(position.HeightPrevious == 0) self.assertTrue(position.ZDelta is None) self.assertTrue(position.ZDeltaPrevious is None) self.assertTrue(position.Layer == 0) self.assertTrue(not position.IsLayerChange) self.assertTrue(not position.IsZHop) self.assertTrue(not position.XHomed) self.assertTrue(not position.YHomed) self.assertTrue(not position.ZHomed) self.assertTrue(not position.HasPositionError) self.assertTrue(not position.IsZHop) self.assertTrue(position.PositionError is None) def test_Home(self): """Test the home command. Make sure the position is set to 0,0,0 after the home.""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) position.Update("G28") self.assertTrue(position.X == None) self.assertTrue(position.XHomed) self.assertTrue(position.Y == None) self.assertTrue(position.YHomed) self.assertTrue(position.ZHomed) self.assertTrue(position.Z == None) self.assertTrue(not position.HasHomedPosition()) position.Reset() position.Update("G28 X") self.assertTrue(position.X == None) self.assertTrue(position.XHomed) self.assertTrue(position.Y is None) self.assertTrue(not position.YHomed) self.assertTrue(position.Z is None) self.assertTrue(not position.ZHomed) self.assertTrue(not position.HasHomedPosition()) position.Reset() position.Update("G28 Y") self.assertTrue(position.X is None) self.assertTrue(not position.XHomed) self.assertTrue(position.Y is None) self.assertTrue(position.YHomed) self.assertTrue(position.Z is None) self.assertTrue(not position.ZHomed) self.assertTrue(not position.HasHomedPosition()) position.Reset() position.Update("G28 Z") self.assertTrue(position.X is None) self.assertTrue(not position.XHomed) self.assertTrue(position.Y is None) self.assertTrue(not position.YHomed) self.assertTrue(position.Z is None) self.assertTrue(position.ZHomed) self.assertTrue(not position.HasHomedPosition()) position.Reset() position.Update("G28 Z X Y") self.assertTrue(position.X is None) self.assertTrue(position.XHomed) self.assertTrue(position.Y is None) self.assertTrue(position.YHomed) self.assertTrue(position.Z is None) self.assertTrue(position.ZHomed) self.assertTrue(not position.HasHomedPosition()) position.Reset() position.Update("G28 W") self.assertTrue(position.X is None) self.assertTrue(position.XHomed) self.assertTrue(position.Y is None) self.assertTrue(position.YHomed) self.assertTrue(position.Z is None) self.assertTrue(position.ZHomed) self.assertTrue(not position.HasHomedPosition()) position.Reset() position.Update("g28") position.Update("g1 x0 y0 z0") # here we have seen the upded coordinates, but we do not know the position self.assertTrue(position.X == 0) self.assertTrue(position.XHomed) self.assertTrue(position.Y == 0) self.assertTrue(position.YHomed) self.assertTrue(position.Z == 0) self.assertTrue(position.ZHomed) self.assertTrue(not position.HasHomedPosition()) # give it another position, now we have homed axis with a known position position.Update("g1 x0 y0 z0") self.assertTrue(position.X == 0) self.assertTrue(position.XHomed) self.assertTrue(position.Y == 0) self.assertTrue(position.YHomed) self.assertTrue(position.Z == 0) self.assertTrue(position.ZHomed) self.assertTrue(position.HasHomedPosition()) def test_UpdatePosition_force(self): """Test the UpdatePosition function with the force option set to true.""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) position.UpdatePosition(x=0, y=0, z=0, e=0, force=True) self.assertTrue(position.X == 0) self.assertTrue(position.Y == 0) self.assertTrue(position.Z == 0) self.assertTrue(position.E == 0) position.UpdatePosition(x=1, y=2, z=3, e=4, force=True) self.assertTrue(position.X == 1) self.assertTrue(position.Y == 2) self.assertTrue(position.Z == 3) self.assertTrue(position.E == 4) position.UpdatePosition(x=None, y=None, z=None, e=None, force=True) self.assertTrue(position.X == 1) self.assertTrue(position.Y == 2) self.assertTrue(position.Z == 3) self.assertTrue(position.E == 4) def test_UpdatePosition_noforce(self): """Test the UpdatePosition function with the force option set to true.""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) # no homed axis position.UpdatePosition(x=0, y=0, z=0, e=0) self.assertTrue(position.X is None) self.assertTrue(position.Y is None) self.assertTrue(position.Z is None) self.assertTrue(position.E == 0) # set homed axis, test absolute position (default) position.XHomed = True position.YHomed = True position.ZHomed = True position.UpdatePosition(x=0, y=0, z=0) self.assertTrue(position.X == 0) self.assertTrue(position.Y == 0) self.assertTrue(position.Z == 0) self.assertTrue(position.E == 0) # update absolute position position.UpdatePosition(x=1, y=2, z=3) self.assertTrue(position.X == 1) self.assertTrue(position.Y == 2) self.assertTrue(position.Z == 3) self.assertTrue(position.E == 0) # set relative position position.IsRelative = True position.UpdatePosition(x=1, y=1, z=1) self.assertTrue(position.X == 2) self.assertTrue(position.Y == 3) self.assertTrue(position.Z == 4) self.assertTrue(position.E == 0) # set extruder absolute position.IsExtruderRelative = False position.UpdatePosition(e=100) self.assertTrue(position.X == 2) self.assertTrue(position.Y == 3) self.assertTrue(position.Z == 4) self.assertTrue(position.E == 100) position.UpdatePosition(e=-10) self.assertTrue(position.X == 2) self.assertTrue(position.Y == 3) self.assertTrue(position.Z == 4) self.assertTrue(position.E == -10) # set extruder relative position.IsExtruderRelative = True position.UpdatePosition(e=20) self.assertTrue(position.X == 2) self.assertTrue(position.Y == 3) self.assertTrue(position.Z == 4) self.assertTrue(position.E == 10) position.UpdatePosition(e=-1) self.assertTrue(position.X == 2) self.assertTrue(position.Y == 3) self.assertTrue(position.Z == 4) self.assertTrue(position.E == 9) position.UpdatePosition(x=1, y=2, z=3, e=4, force=True) self.assertTrue(position.X == 1) self.assertTrue(position.Y == 2) self.assertTrue(position.Z == 3) self.assertTrue(position.E == 4) position.UpdatePosition(x=None, y=None, z=None, e=None, force=True) self.assertTrue(position.X == 1) self.assertTrue(position.Y == 2) self.assertTrue(position.Z == 3) self.assertTrue(position.E == 4) 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.XHomed = True position.YHomed = True position.ZHomed = True # set absolute mode with G90 position.Update("g90;") # update the position to 10 (absolute) position.UpdatePosition(e=10) self.assertTrue(position.E == 10) # update the position to 10 again (absolute) to make sure we are in absolute coordinates. position.UpdatePosition(e=10) self.assertTrue(position.E == 10) # set relative mode with G90 position.Update("g91;") # update the position to 20 (relative) position.UpdatePosition(e=20) self.assertTrue(position.E == 30) def test_G90InfluencesExtruder_Update(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.XHomed = True position.YHomed = True position.ZHomed = True # set absolute mode with G90 position.Update("g90;") # update the position to 10 (absolute) position.Update("G1 E10.0") self.assertTrue(position.E == 10) # update the position to 10 again (absolute) to make sure we are in absolute coordinates. position.Update("G1 E10.0") self.assertTrue(position.E == 10) # set relative mode with G90 position.Update("g91;") # update the position to 20 (relative) position.Update("G1 E20.0") self.assertTrue(position.E == 30) def test_Update(self): """Test the UpdatePosition function with the force option set to true.""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) # no homed axis position.Update("G1 x100 y200 z300") self.assertTrue(position.X is None) self.assertTrue(position.Y is None) self.assertTrue(position.Z is None) # set homed axis and update absolute position position.Update("G28") position.Update("G1 x100 y200 z150") self.assertTrue(position.X == 100) self.assertTrue(position.Y == 200) self.assertTrue(position.Z == 150) # move again and retest position.Update("G1 x101 y199 z151") self.assertTrue(position.X == 101) self.assertTrue(position.Y == 199) self.assertTrue(position.Z == 151) # switch to relative and update position position.Update("G91") position.Update("G1 x-1 y-1 z1.0") self.assertTrue(position.X == 100) self.assertTrue(position.Y == 198) self.assertTrue(position.Z == 152) # move again and retest position.Update("G1 x-99 y-196 z-149.0") self.assertTrue(position.X == 1) self.assertTrue(position.Y == 2) self.assertTrue(position.Z == 3) # go back to absolute and move to origin position.Update("G90") position.Update("G1 x0 y0 z0.0") self.assertTrue(position.X == 0) self.assertTrue(position.Y == 0) self.assertTrue(position.Z == 0) #G92 Test Set Position def test_G92SetPosition(self): """Test the G92 command, settings the position.""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) # no homed axis position.Update("G92 x10 y20 z30") self.assertTrue(position.X is None) self.assertTrue(position.Y is None) self.assertTrue(position.Z is None) # set homed axis, absolute coordinates, and set position position.Update("G28") position.Update("G90") position.Update("G1 x100 y200 z150") position.Update("G92 x10 y20 z30") self.assertTrue(position.X == 100) self.assertTrue(position.XOffset == 90) self.assertTrue(position.Y == 200) self.assertTrue(position.YOffset == 180) self.assertTrue(position.Z == 150) self.assertTrue(position.ZOffset == 120) # Move to same position and retest position.Update("G1 x0 y0 z0") self.assertTrue(position.X == 90) self.assertTrue(position.XOffset == 90) self.assertTrue(position.Y == 180) self.assertTrue(position.YOffset == 180) self.assertTrue(position.Z == 120) self.assertTrue(position.ZOffset == 120) # Move and retest position.Update("G1 x-10 y10 z20") self.assertTrue(position.X == 80) self.assertTrue(position.XOffset == 90) self.assertTrue(position.Y == 190) self.assertTrue(position.YOffset == 180) self.assertTrue(position.Z == 140) self.assertTrue(position.ZOffset == 120) # G92 with no parameters position.Update("G92") self.assertTrue(position.X == 80) self.assertTrue(position.XOffset == 80) self.assertTrue(position.Y == 190) self.assertTrue(position.YOffset == 190) self.assertTrue(position.Z == 140) self.assertTrue(position.ZOffset == 140) #G92 Test Absolute Movement 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("G28") position.Update("G90") position.Update("G1 x100 y200 z150") position.Update("G92 x10 y20 z30") self.assertTrue(position.X == 100) self.assertTrue(position.XOffset == 90) self.assertTrue(position.Y == 200) self.assertTrue(position.YOffset == 180) self.assertTrue(position.Z == 150) self.assertTrue(position.ZOffset == 120) # move to origin position.Update("G1 x-90 y-180 z-120") self.assertTrue(position.X == 0) self.assertTrue(position.XOffset == 90) self.assertTrue(position.Y == 0) self.assertTrue(position.YOffset == 180) self.assertTrue(position.Z == 0) self.assertTrue(position.ZOffset == 120) # move back position.Update("G1 x0 y0 z0") self.assertTrue(position.X == 90) self.assertTrue(position.XOffset == 90) self.assertTrue(position.Y == 180) self.assertTrue(position.YOffset == 180) self.assertTrue(position.Z == 120) self.assertTrue(position.ZOffset == 120) #G92 Test Relative Movement 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("G28") position.Update("G91") position.Update("G1 x100 y200 z150") position.Update("G92 x10 y20 z30") self.assertTrue(position.X is None) self.assertTrue(position.XOffset == 90) self.assertTrue(position.Y == 200) self.assertTrue(position.YOffset == 180) self.assertTrue(position.Z == 150) self.assertTrue(position.ZOffset == 120) # move to origin position.Update("G1 x-100 y-200 z-150") self.assertTrue(position.X == 0) self.assertTrue(position.XOffset == 90) self.assertTrue(position.Y == 0) self.assertTrue(position.YOffset == 180) self.assertTrue(position.Z == 0) self.assertTrue(position.ZOffset == 120) # advance each axis position.Update("G1 x1 y2 z3") self.assertTrue(position.X == 1) self.assertTrue(position.XOffset == 90) self.assertTrue(position.Y == 2) self.assertTrue(position.YOffset == 180) self.assertTrue(position.Z == 3) self.assertTrue(position.ZOffset == 120) # advance again position.Update("G1 x1 y2 z3") self.assertTrue(position.X == 2) self.assertTrue(position.XOffset == 90) self.assertTrue(position.Y == 4) self.assertTrue(position.YOffset == 180) self.assertTrue(position.Z == 6) self.assertTrue(position.ZOffset == 120) def test_HeightAndLayerChanges(self): """Test the height and layer changes.""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) # test initial state self.assertTrue(position.Height is None) self.assertTrue(position.HeightPrevious == 0) self.assertTrue(position.Layer == 0) self.assertTrue(not position.IsLayerChange) # check without homed axis position.Update("G1 x0 y0 z0.20000 e1") self.assertTrue(position.Height is None) self.assertTrue(position.HeightPrevious is None) self.assertTrue(position.Layer == 0) self.assertTrue(not position.IsLayerChange) # set homed axis, absolute coordinates, and check height and layer position.Update("G28") self.assertTrue(position.Height is None) self.assertTrue(position.HeightPrevious is None) self.assertTrue(position.Layer == 0) self.assertTrue(not position.IsLayerChange) # move without extruding, height and layer should not change position.Update("G1 x100 y200 z150") self.assertTrue(position.Height is None) self.assertTrue(position.HeightPrevious is None) self.assertTrue(position.Layer == 0) self.assertTrue(not position.IsLayerChange) # move to origin, height and layer stuff should stay the same position.Update("G1 x0 y0 z0") self.assertTrue(position.Height is None) self.assertTrue(position.HeightPrevious is None) self.assertTrue(position.Layer == 0) self.assertTrue(not position.IsLayerChange) # extrude, height change! position.Update("G1 x0 y0 z0 e1") self.assertTrue(position.Height == 0) self.assertTrue(position.HeightPrevious == 0) self.assertTrue(position.Layer == 1) self.assertTrue(position.IsLayerChange) #extrude higher, update layer., this will get rounded to 0.2 position.Update("G1 x0 y0 z0.1999 e1") self.assertTrue(position.Height == 0.2) self.assertTrue(position.HeightPrevious == 0) self.assertTrue(position.Layer == 2) self.assertTrue(position.IsLayerChange) # extrude just slightly higher, but with rounding on the same layer position.Update("G1 x0 y0 z0.20000 e1") self.assertTrue(position.Height == .2) self.assertTrue(position.HeightPrevious == 0.2) self.assertTrue(position.Layer == 2) self.assertTrue(not position.IsLayerChange) # extrude again on same layer - Height Previous should now be updated, and IsLayerChange should be false position.Update("G1 x0 y0 z0.20000 e1") self.assertTrue(position.Height == .2) self.assertTrue(position.HeightPrevious == .2) self.assertTrue(position.Layer == 2) self.assertTrue(not position.IsLayerChange) # extrude again on same layer - No changes position.Update("G1 x0 y0 z0.20000 e1") self.assertTrue(position.Height == .2) self.assertTrue(position.HeightPrevious == .2) self.assertTrue(position.Layer == 2) self.assertTrue(not position.IsLayerChange) # extrude below the current layer - No changes position.Update("G1 x0 y0 z0.00000 e1") self.assertTrue(position.Height == .2) self.assertTrue(position.HeightPrevious == .2) self.assertTrue(position.Layer == 2) self.assertTrue(not position.IsLayerChange) # extrude up higher and change the height/layer. Should never happen, but it's an interesting test case position.Update("G1 x0 y0 z0.60000 e1") self.assertTrue(position.Height == .6) self.assertTrue(position.HeightPrevious == .2) self.assertTrue(position.Layer == 3) self.assertTrue(position.IsLayerChange) # extrude up again position.Update("G1 x0 y0 z0.65000 e1") self.assertTrue(position.Height == .65) self.assertTrue(position.HeightPrevious == .6) self.assertTrue(position.Layer == 4) self.assertTrue(position.IsLayerChange) # extrude on previous layer position.Update("G1 x0 y0 z0.60000 e1") self.assertTrue(position.Height == .65) self.assertTrue(position.HeightPrevious == .65) self.assertTrue(position.Layer == 4) self.assertTrue(not position.IsLayerChange) # extrude on previous layer again position.Update("G1 x0 y0 z0.60000 e1") self.assertTrue(position.Height == .65) self.assertTrue(position.HeightPrevious == .65) self.assertTrue(position.Layer == 4) self.assertTrue(not position.IsLayerChange) # move up but do not extrude position.Update("G1 x0 y0 z0.70000") self.assertTrue(position.Height == .65) self.assertTrue(position.HeightPrevious == .65) self.assertTrue(position.Layer == 4) self.assertTrue(not position.IsLayerChange) # move up but do not extrude a second time position.Update("G1 x0 y0 z0.80000") self.assertTrue(position.Height == .65) self.assertTrue(position.HeightPrevious == .65) self.assertTrue(position.Layer == 4) self.assertTrue(not position.IsLayerChange) # extrude at a different height position.Update("G1 x0 y0 z0.85000 e.001") self.assertTrue(position.Height == .85) self.assertTrue(position.HeightPrevious == .65) self.assertTrue(position.Layer == 5) self.assertTrue(position.IsLayerChange) #M82 and M83 - Test extruder movement def test_ExtruderMovement(self): """Test the M82 and M83 command.""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) # test initial position self.assertTrue(position.E == 0) self.assertTrue(position.IsExtruderRelative == True) self.assertTrue(position.ERelative() == 0) # test movement position.Update("G0 E100") self.assertTrue(position.E == 100) self.assertTrue(position.ERelative() == 100) # switch to absolute movement position.Update("M82") self.assertTrue(position.IsExtruderRelative == False) self.assertTrue(position.E == 100) self.assertTrue(position.ERelative() == 0) # move to -25 position.Update("G0 E-25") self.assertTrue(position.E == -25) self.assertTrue(position.ERelative() == -125) # test movement to origin position.Update("G0 E0") self.assertTrue(position.E == 0) self.assertTrue(position.ERelative() == 25) # switch to relative position position.Update("M83") position.Update("G0 e1.1") self.assertTrue(position.E == 1.1) self.assertTrue(position.ERelative() == 1.1) # move and test position.Update("G0 e1.1") self.assertTrue(position.E == 2.2) self.assertTrue(position.ERelative() == 1.1) # move and test position.Update("G0 e-2.2") self.assertTrue(position.E == 0) self.assertTrue(position.ERelative() == -2.2) def test_zHop(self): """Test zHop detection.""" # set zhop distance self.Settings.CurrentPrinter().z_hop = .5 position = Position(self.Settings, self.OctoprintPrinterProfile, False) # test initial state self.assertTrue(not position.IsZHop) # check without homed axis position.Update("G1 x0 y0 z0") self.assertTrue(not position.IsZHop) position.Update("G1 x0 y0 z0.5") self.assertTrue(not position.IsZHop) # Home axis, check again position.Update("G28") self.assertTrue(not position.IsZHop) # Position reports as NotHomed (misnomer, need to replace), needs to get coordinates position.Update("G1 x0 y0 z0") # Move up without extrude, this is not a zhop since we haven't extruded anything! position.Update("g0 z0.5") self.assertTrue(not position.IsZHop) # move back down to 0 and extrude position.Update("g0 z0 e1") self.assertTrue(not position.IsZHop) # Move up without extrude, this should trigger zhop start position.Update("g0 z0.5") self.assertTrue(position.IsZHop) # move below zhop threshold position.Update("g0 z0.3") self.assertTrue(position.IsZHop) # move right up to zhop without going over, we are within the rounding error position.Update("g0 z0.4999") self.assertTrue(position.IsZHop) # Extrude on z5 position.Update("g0 z0.5 e1") self.assertTrue(position.IsZHop) # partial z lift, , we are within the rounding error position.Update("g0 z0.9999") self.assertTrue(position.IsZHop) # zhop to 1 position.Update("g0 z1") self.assertTrue(position.IsZHop) # test with extrusion start at 1.5 position.Update("g0 z1.5 e1") self.assertTrue(position.IsZHop) # test with extrusion at 2 position.Update("g0 z2 e1") self.assertTrue(not position.IsZHop) #zhop position.Update("g0 z2.5 e0") self.assertTrue(position.IsZHop) # do not move extruder position.Update("no-command") self.assertTrue(position.IsZHop) # todo: IsAtCurrent/PreviousPosition tests 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("g28") position.Update("G1 X119.915 Y113.338 Z2.1 F7200") self.assertTrue(position.IsAtCurrentPosition(119.91, 113.34, 2.1)) position.Update("g0 x120 y121 z2.1") self.assertTrue(position.IsAtPreviousPosition(119.91, 113.34, 2.1))
def setUp(self): self.Settings = OctolapseSettings("c:\\temp\\octolapse.log") self.Extruder = Extruder(self.Settings)
class Test_SnapshotGcode(unittest.TestCase): def setUp(self): self.Settings = OctolapseSettings("c:\\temp\\octolapse.log") self.Extruder = Extruder(self.Settings) def tearDown(self): del self.Settings del self.Extruder def CreateOctoprintPrinterProfile(self): return dict(volume=dict( width=250, depth=200, height=200, formFactor="Not A Circle", custom_box=False, )) def test_GetSnapshotPosition_Absolute(self): """Test getting absolute snapshot positions for x and y""" # adjust the settings for absolute position and create the snapshot gcode generator self.Settings.CurrentStabilization().x_type = "fixed_coordinate" self.Settings.CurrentStabilization().x_fixed_coordinate = 10 self.Settings.CurrentStabilization().y_type = "fixed_coordinate" self.Settings.CurrentStabilization().y_fixed_coordinate = 20 snapshotGcodeGenerator = SnapshotGcodeGenerator( self.Settings, self.CreateOctoprintPrinterProfile()) # get the coordinates and test coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 10 and coords["Y"] == 20) # get the coordinates and test coords = snapshotGcodeGenerator.GetSnapshotPosition(1, 1) self.assertTrue(coords["X"] == 10 and coords["Y"] == 20) # get the coordinates and test coords = snapshotGcodeGenerator.GetSnapshotPosition(100, 100) self.assertTrue(coords["X"] == 10 and coords["Y"] == 20) def test_GetSnapshotPosition_AbsolutePath(self): """Test getting absolute path snapshot positions for x and y""" # adjust the settings for absolute position and create the snapshot gcode generator self.Settings.CurrentStabilization().x_type = "fixed_path" self.Settings.CurrentStabilization().x_fixed_path = "0,1,2,3,4,5" self.Settings.CurrentStabilization().y_type = "fixed_path" self.Settings.CurrentStabilization().y_fixed_path = "5,4,3,2,1,0" # test with no loop self.Settings.CurrentStabilization().x_fixed_path_loop = False self.Settings.CurrentStabilization().x_fixed_path_invert_loop = False self.Settings.CurrentStabilization().y_fixed_path_loop = False self.Settings.CurrentStabilization().y_fixed_path_invert_loop = False snapshotGcodeGenerator = SnapshotGcodeGenerator( self.Settings, self.CreateOctoprintPrinterProfile()) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 0 and coords["Y"] == 5) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 1 and coords["Y"] == 4) coords = snapshotGcodeGenerator.GetSnapshotPosition(1, 0) self.assertTrue(coords["X"] == 2 and coords["Y"] == 3) coords = snapshotGcodeGenerator.GetSnapshotPosition(1, 1) self.assertTrue(coords["X"] == 3 and coords["Y"] == 2) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 1) self.assertTrue(coords["X"] == 4 and coords["Y"] == 1) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 5 and coords["Y"] == 0) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 5 and coords["Y"] == 0) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 5 and coords["Y"] == 0) # test with loop, no invert self.Settings.CurrentStabilization().x_fixed_path_loop = True self.Settings.CurrentStabilization().x_fixed_path_invert_loop = False self.Settings.CurrentStabilization().y_fixed_path_loop = True self.Settings.CurrentStabilization().y_fixed_path_invert_loop = False snapshotGcodeGenerator = SnapshotGcodeGenerator( self.Settings, self.CreateOctoprintPrinterProfile()) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 0 and coords["Y"] == 5) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 1 and coords["Y"] == 4) coords = snapshotGcodeGenerator.GetSnapshotPosition(1, 0) self.assertTrue(coords["X"] == 2 and coords["Y"] == 3) coords = snapshotGcodeGenerator.GetSnapshotPosition(1, 1) self.assertTrue(coords["X"] == 3 and coords["Y"] == 2) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 1) self.assertTrue(coords["X"] == 4 and coords["Y"] == 1) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 5 and coords["Y"] == 0) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 0 and coords["Y"] == 5) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 1 and coords["Y"] == 4) # test with loop and invert self.Settings.CurrentStabilization().x_fixed_path_loop = True self.Settings.CurrentStabilization().x_fixed_path_invert_loop = True self.Settings.CurrentStabilization().y_fixed_path_loop = True self.Settings.CurrentStabilization().y_fixed_path_invert_loop = True snapshotGcodeGenerator = SnapshotGcodeGenerator( self.Settings, self.CreateOctoprintPrinterProfile()) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 0 and coords["Y"] == 5) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 1 and coords["Y"] == 4) coords = snapshotGcodeGenerator.GetSnapshotPosition(1, 0) self.assertTrue(coords["X"] == 2 and coords["Y"] == 3) coords = snapshotGcodeGenerator.GetSnapshotPosition(1, 1) self.assertTrue(coords["X"] == 3 and coords["Y"] == 2) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 1) self.assertTrue(coords["X"] == 4 and coords["Y"] == 1) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 5 and coords["Y"] == 0) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 4 and coords["Y"] == 1) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 3 and coords["Y"] == 2) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 2 and coords["Y"] == 3) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 1 and coords["Y"] == 4) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 0 and coords["Y"] == 5) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 1 and coords["Y"] == 4) def test_GetSnapshotPosition_BedRelative(self): """Test getting bed relative snapshot positions for x and y""" # adjust the settings for absolute position and create the snapshot gcode generator self.Settings.CurrentStabilization().x_type = "relative" self.Settings.CurrentStabilization().x_relative = 0 self.Settings.CurrentStabilization().y_type = "relative" self.Settings.CurrentStabilization().y_relative = 100 snapshotGcodeGenerator = SnapshotGcodeGenerator( self.Settings, self.CreateOctoprintPrinterProfile()) # get the coordinates and test coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 0 and coords["Y"] == 200) # get the coordinates and test coords = snapshotGcodeGenerator.GetSnapshotPosition(1, 1) self.assertTrue(coords["X"] == 0 and coords["Y"] == 200) # get the coordinates and test coords = snapshotGcodeGenerator.GetSnapshotPosition(100, 100) self.assertTrue(coords["X"] == 0 and coords["Y"] == 200) def test_GetSnapshotPosition_BedRelativePath(self): """Test getting bed relative path snapshot positions for x and y""" # adjust the settings for absolute position and create the snapshot gcode generator self.Settings.CurrentStabilization().x_type = "relative_path" self.Settings.CurrentStabilization().x_relative_path = "0,25,50,75,100" self.Settings.CurrentStabilization().y_type = "relative_path" self.Settings.CurrentStabilization().y_relative_path = "100,75,50,25,0" # test with no loop self.Settings.CurrentStabilization().x_relative_path_loop = False self.Settings.CurrentStabilization( ).x_relative_path_invert_loop = False self.Settings.CurrentStabilization().y_relative_path_loop = False self.Settings.CurrentStabilization( ).y_relative_path_invert_loop = False snapshotGcodeGenerator = SnapshotGcodeGenerator( self.Settings, self.CreateOctoprintPrinterProfile()) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 0 and coords["Y"] == 200) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 62.5 and coords["Y"] == 150) coords = snapshotGcodeGenerator.GetSnapshotPosition(1, 0) self.assertTrue(coords["X"] == 125 and coords["Y"] == 100) coords = snapshotGcodeGenerator.GetSnapshotPosition(1, 1) self.assertTrue(coords["X"] == 187.5 and coords["Y"] == 50) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 1) self.assertTrue(coords["X"] == 250 and coords["Y"] == 0) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 250 and coords["Y"] == 0) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 250 and coords["Y"] == 0) # test with loop, no invert self.Settings.CurrentStabilization().x_relative_path_loop = True self.Settings.CurrentStabilization( ).x_relative_path_invert_loop = False self.Settings.CurrentStabilization().y_relative_path_loop = True self.Settings.CurrentStabilization( ).y_relative_path_invert_loop = False snapshotGcodeGenerator = SnapshotGcodeGenerator( self.Settings, self.CreateOctoprintPrinterProfile()) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 0 and coords["Y"] == 200) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 62.5 and coords["Y"] == 150) coords = snapshotGcodeGenerator.GetSnapshotPosition(1, 0) self.assertTrue(coords["X"] == 125 and coords["Y"] == 100) coords = snapshotGcodeGenerator.GetSnapshotPosition(1, 1) self.assertTrue(coords["X"] == 187.5 and coords["Y"] == 50) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 1) self.assertTrue(coords["X"] == 250 and coords["Y"] == 0) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 0 and coords["Y"] == 200) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 62.5 and coords["Y"] == 150) # test with loop and invert self.Settings.CurrentStabilization().x_relative_path_loop = True self.Settings.CurrentStabilization().x_relative_path_invert_loop = True self.Settings.CurrentStabilization().y_relative_path_loop = True self.Settings.CurrentStabilization().y_relative_path_invert_loop = True snapshotGcodeGenerator = SnapshotGcodeGenerator( self.Settings, self.CreateOctoprintPrinterProfile()) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 0 and coords["Y"] == 200) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 62.5 and coords["Y"] == 150) coords = snapshotGcodeGenerator.GetSnapshotPosition(1, 0) self.assertTrue(coords["X"] == 125 and coords["Y"] == 100) coords = snapshotGcodeGenerator.GetSnapshotPosition(1, 1) self.assertTrue(coords["X"] == 187.5 and coords["Y"] == 50) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 1) self.assertTrue(coords["X"] == 250 and coords["Y"] == 0) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 187.5 and coords["Y"] == 50) coords = snapshotGcodeGenerator.GetSnapshotPosition(0, 0) self.assertTrue(coords["X"] == 125 and coords["Y"] == 100) 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.CurrentStabilization().x_type = "fixed_coordinate" self.Settings.CurrentStabilization().x_fixed_coordinate = 10 self.Settings.CurrentStabilization().y_type = "fixed_coordinate" self.Settings.CurrentStabilization().y_fixed_coordinate = 20 snapshotGcodeGenerator = SnapshotGcodeGenerator( self.Settings, self.CreateOctoprintPrinterProfile()) self.Extruder.IsRetracted = True snapshotGcode = snapshotGcodeGenerator.CreateSnapshotGcode( 0, 0, 0, False, True, self.Extruder, "SavedCommand") # verify the created gcode # this line should switch from absolute to relative for the ZHop self.assertTrue(snapshotGcode.GcodeCommands[0] == "G91") # this line should zhop by 0.500 mm self.assertTrue(snapshotGcode.GcodeCommands[1] == "G1 Z0.500 F7200") # this line should switch to absolute coordinates in prep for move self.assertTrue(snapshotGcode.GcodeCommands[2] == "G90") # this line should switch back to absolute coordinates self.assertTrue( snapshotGcode.GcodeCommands[3] == "G1 X10.000 Y20.000 F7200") # move back to the return position self.assertTrue( snapshotGcode.GcodeCommands[4] == "G1 X0.000 Y0.000 F7200") # change to relative coordinates self.assertTrue(snapshotGcode.GcodeCommands[5] == "G91") # this line should zhop by -0.500 mm self.assertTrue(snapshotGcode.GcodeCommands[6] == "G1 Z-0.500 F7200") # change back to the original coordinate system (absolute) self.assertTrue(snapshotGcode.GcodeCommands[7] == "G90") # the saved command self.assertTrue(snapshotGcode.GcodeCommands[8] == "SavedCommand") # verify the return commands self.assertTrue( snapshotGcode.ReturnCommands()[0] == "G1 X0.000 Y0.000 F7200") self.assertTrue(snapshotGcode.ReturnCommands()[1] == "G91") self.assertTrue( snapshotGcode.ReturnCommands()[2] == "G1 Z-0.500 F7200") self.assertTrue(snapshotGcode.ReturnCommands()[3] == "G90") self.assertTrue(snapshotGcode.ReturnCommands()[4] == "SavedCommand") # verify the snapshot commands self.assertTrue(snapshotGcode.SnapshotCommands()[0] == "G91") self.assertTrue( snapshotGcode.SnapshotCommands()[1] == "G1 Z0.500 F7200") self.assertTrue(snapshotGcode.SnapshotCommands()[2] == "G90") self.assertTrue( snapshotGcode.SnapshotCommands()[3] == "G1 X10.000 Y20.000 F7200") # verify the indexes of the generated gcode self.assertTrue(snapshotGcode.SnapshotIndex == 3) self.assertTrue(snapshotGcode.EndIndex() == 8) # verify the return coordinates self.assertTrue(snapshotGcode.ReturnX == 0) self.assertTrue(snapshotGcode.ReturnY == 0) self.assertTrue(snapshotGcode.ReturnZ == 0) def test_GetSnapshotGcode_RelativePath_RelativeCoordinates_ExtruderAbsolute_ZHop_Retraction( self): # test with relative paths, absolute extruder coordinates, retract and z hop # use relative coordinates for stabilizations self.Settings.CurrentStabilization().x_type = "relative_path" self.Settings.CurrentStabilization( ).x_relative_path = "50,100" #125,250 self.Settings.CurrentStabilization().x_relative_path_loop = False self.Settings.CurrentStabilization( ).x_relative_path_invert_loop = False self.Settings.CurrentStabilization().y_type = "relative_path" self.Settings.CurrentStabilization( ).y_relative_path = "50,100" #100,200 self.Settings.CurrentStabilization().y_relative_path_loop = False self.Settings.CurrentStabilization( ).y_relative_path_invert_loop = False self.Settings.CurrentSnapshot().retract_before_move = True snapshotGcodeGenerator = SnapshotGcodeGenerator( self.Settings, self.CreateOctoprintPrinterProfile()) snapshotGcode = snapshotGcodeGenerator.CreateSnapshotGcode( 10, 10, 10, True, False, self.Extruder, "SavedCommand") # verify the created gcode # this line should switch to absolute coordinates in prep for move self.assertTrue(snapshotGcode.GcodeCommands[0] == "M83") self.assertTrue(snapshotGcode.GcodeCommands[1] == "G1 E-4.000 F4800") self.assertTrue(snapshotGcode.GcodeCommands[2] == "G1 Z0.500 F7200") self.assertTrue(snapshotGcode.GcodeCommands[3] == "G90") self.assertTrue( snapshotGcode.GcodeCommands[4] == "G1 X125.000 Y100.000 F7200") # move back to the return position self.assertTrue( snapshotGcode.GcodeCommands[5] == "G1 X10.000 Y10.000 F7200") # change to relative coordinates self.assertTrue(snapshotGcode.GcodeCommands[6] == "G91") self.assertTrue(snapshotGcode.GcodeCommands[7] == "G1 Z-0.500 F7200") self.assertTrue(snapshotGcode.GcodeCommands[8] == "G1 E4.000 F4800") self.assertTrue(snapshotGcode.GcodeCommands[9] == "M82") # the saved command self.assertTrue(snapshotGcode.GcodeCommands[10] == "SavedCommand") # verify the return commands self.assertTrue( snapshotGcode.ReturnCommands()[0] == "G1 X10.000 Y10.000 F7200") self.assertTrue(snapshotGcode.ReturnCommands()[1] == "G91") self.assertTrue( snapshotGcode.ReturnCommands()[2] == "G1 Z-0.500 F7200") self.assertTrue(snapshotGcode.ReturnCommands()[3] == "G1 E4.000 F4800") self.assertTrue(snapshotGcode.ReturnCommands()[4] == "M82") self.assertTrue(snapshotGcode.ReturnCommands()[5] == "SavedCommand") # verify the snapshot commands self.assertTrue(snapshotGcode.SnapshotCommands()[0] == "M83") self.assertTrue( snapshotGcode.SnapshotCommands()[1] == "G1 E-4.000 F4800") self.assertTrue( snapshotGcode.SnapshotCommands()[2] == "G1 Z0.500 F7200") self.assertTrue(snapshotGcode.SnapshotCommands()[3] == "G90") self.assertTrue(snapshotGcode.SnapshotCommands()[4] == "G1 X125.000 Y100.000 F7200") # verify the indexes of the generated gcode self.assertTrue(snapshotGcode.SnapshotIndex == 4) self.assertTrue(snapshotGcode.EndIndex() == 10) # verify the return coordinates self.assertTrue(snapshotGcode.ReturnX == 10) self.assertTrue(snapshotGcode.ReturnY == 10) self.assertTrue(snapshotGcode.ReturnZ == 10) # test the second coordinate in the path snapshotGcode = snapshotGcodeGenerator.CreateSnapshotGcode( 10, 10, 10, True, False, self.Extruder, "SavedCommand") # verify the created gcode # this line should switch to absolute coordinates in prep for move self.assertTrue(snapshotGcode.GcodeCommands[0] == "M83") self.assertTrue(snapshotGcode.GcodeCommands[1] == "G1 E-4.000 F4800") self.assertTrue(snapshotGcode.GcodeCommands[2] == "G1 Z0.500 F7200") self.assertTrue(snapshotGcode.GcodeCommands[3] == "G90") self.assertTrue( snapshotGcode.GcodeCommands[4] == "G1 X250.000 Y200.000 F7200") # move back to the return position self.assertTrue( snapshotGcode.GcodeCommands[5] == "G1 X10.000 Y10.000 F7200") # change to relative coordinates self.assertTrue(snapshotGcode.GcodeCommands[6] == "G91") self.assertTrue(snapshotGcode.GcodeCommands[7] == "G1 Z-0.500 F7200") self.assertTrue(snapshotGcode.GcodeCommands[8] == "G1 E4.000 F4800") self.assertTrue(snapshotGcode.GcodeCommands[9] == "M82") # the saved command self.assertTrue(snapshotGcode.GcodeCommands[10] == "SavedCommand") # verify the return commands self.assertTrue( snapshotGcode.ReturnCommands()[0] == "G1 X10.000 Y10.000 F7200") self.assertTrue(snapshotGcode.ReturnCommands()[1] == "G91") self.assertTrue( snapshotGcode.ReturnCommands()[2] == "G1 Z-0.500 F7200") self.assertTrue(snapshotGcode.ReturnCommands()[3] == "G1 E4.000 F4800") self.assertTrue(snapshotGcode.ReturnCommands()[4] == "M82") self.assertTrue(snapshotGcode.ReturnCommands()[5] == "SavedCommand") # verify the snapshot commands self.assertTrue(snapshotGcode.SnapshotCommands()[0] == "M83") self.assertTrue( snapshotGcode.SnapshotCommands()[1] == "G1 E-4.000 F4800") self.assertTrue( snapshotGcode.SnapshotCommands()[2] == "G1 Z0.500 F7200") self.assertTrue(snapshotGcode.SnapshotCommands()[3] == "G90") self.assertTrue(snapshotGcode.SnapshotCommands()[4] == "G1 X250.000 Y200.000 F7200") # verify the indexes of the generated gcode self.assertTrue(snapshotGcode.SnapshotIndex == 4) self.assertTrue(snapshotGcode.EndIndex() == 10) # verify the return coordinates self.assertTrue(snapshotGcode.ReturnX == 10) self.assertTrue(snapshotGcode.ReturnY == 10) self.assertTrue(snapshotGcode.ReturnZ == 10) def test_GetSnapshotGcode_FixedPath_RelativeCoordinates_ExtruderAbsolute_ZHop_AlreadyRetracted( self): # test with relative paths, absolute extruder coordinates, retract and z hop # use relative coordinates for stabilizations self.Settings.CurrentStabilization().x_type = "fixed_path" self.Settings.CurrentStabilization().x_fixed_path = "50,100" #125,250 self.Settings.CurrentStabilization().x_fixed_path_loop = False self.Settings.CurrentStabilization().x_fixed_path_invert_loop = False self.Settings.CurrentStabilization().y_type = "fixed_path" self.Settings.CurrentStabilization().y_fixed_path = "50,100" #100,200 self.Settings.CurrentStabilization().y_fixed_path_loop = False self.Settings.CurrentStabilization().y_fixed_path_invert_loop = False self.Settings.CurrentSnapshot().retract_before_move = True snapshotGcodeGenerator = SnapshotGcodeGenerator( self.Settings, self.CreateOctoprintPrinterProfile()) self.Extruder.IsRetracted = True snapshotGcode = snapshotGcodeGenerator.CreateSnapshotGcode( 100, 50, 0, True, False, self.Extruder, "SavedCommand") # verify the created gcode # this line should switch to absolute coordinates in prep for move self.assertTrue(snapshotGcode.GcodeCommands[0] == "G1 Z0.500 F7200") self.assertTrue(snapshotGcode.GcodeCommands[1] == "G90") self.assertTrue( snapshotGcode.GcodeCommands[2] == "G1 X50.000 Y50.000 F7200") # move back to the return position self.assertTrue( snapshotGcode.GcodeCommands[3] == "G1 X100.000 Y50.000 F7200") # change to relative coordinates self.assertTrue(snapshotGcode.GcodeCommands[4] == "G91") self.assertTrue(snapshotGcode.GcodeCommands[5] == "G1 Z-0.500 F7200") # the saved command self.assertTrue(snapshotGcode.GcodeCommands[6] == "SavedCommand") # verify the return commands self.assertTrue( snapshotGcode.ReturnCommands()[0] == "G1 X100.000 Y50.000 F7200") self.assertTrue(snapshotGcode.ReturnCommands()[1] == "G91") self.assertTrue( snapshotGcode.ReturnCommands()[2] == "G1 Z-0.500 F7200") self.assertTrue(snapshotGcode.ReturnCommands()[3] == "SavedCommand") # verify the snapshot commands self.assertTrue( snapshotGcode.SnapshotCommands()[0] == "G1 Z0.500 F7200") self.assertTrue(snapshotGcode.SnapshotCommands()[1] == "G90") self.assertTrue( snapshotGcode.SnapshotCommands()[2] == "G1 X50.000 Y50.000 F7200") # verify the indexes of the generated gcode self.assertTrue(snapshotGcode.SnapshotIndex == 2) self.assertTrue(snapshotGcode.EndIndex() == 6) # verify the return coordinates self.assertTrue(snapshotGcode.ReturnX == 100) self.assertTrue(snapshotGcode.ReturnY == 50) self.assertTrue(snapshotGcode.ReturnZ == 0) # Get the next coordinate in the path snapshotGcode = snapshotGcodeGenerator.CreateSnapshotGcode( 101, 51, 0, True, False, self.Extruder, "SavedCommand") # verify the created gcode # this line should switch to absolute coordinates in prep for move self.assertTrue(snapshotGcode.GcodeCommands[0] == "G1 Z0.500 F7200") self.assertTrue(snapshotGcode.GcodeCommands[1] == "G90") self.assertTrue( snapshotGcode.GcodeCommands[2] == "G1 X100.000 Y100.000 F7200") # move back to the return position self.assertTrue( snapshotGcode.GcodeCommands[3] == "G1 X101.000 Y51.000 F7200") # change to relative coordinates self.assertTrue(snapshotGcode.GcodeCommands[4] == "G91") self.assertTrue(snapshotGcode.GcodeCommands[5] == "G1 Z-0.500 F7200") # the saved command self.assertTrue(snapshotGcode.GcodeCommands[6] == "SavedCommand") # verify the return commands self.assertTrue( snapshotGcode.ReturnCommands()[0] == "G1 X101.000 Y51.000 F7200") self.assertTrue(snapshotGcode.ReturnCommands()[1] == "G91") self.assertTrue( snapshotGcode.ReturnCommands()[2] == "G1 Z-0.500 F7200") self.assertTrue(snapshotGcode.ReturnCommands()[3] == "SavedCommand") # verify the snapshot commands self.assertTrue( snapshotGcode.SnapshotCommands()[0] == "G1 Z0.500 F7200") self.assertTrue(snapshotGcode.SnapshotCommands()[1] == "G90") self.assertTrue(snapshotGcode.SnapshotCommands()[2] == "G1 X100.000 Y100.000 F7200") # verify the indexes of the generated gcode self.assertTrue(snapshotGcode.SnapshotIndex == 2) self.assertTrue(snapshotGcode.EndIndex() == 6) # verify the return coordinates self.assertTrue(snapshotGcode.ReturnX == 101) self.assertTrue(snapshotGcode.ReturnY == 51) self.assertTrue(snapshotGcode.ReturnZ == 0) # test the second coordinate in the path snapshotGcode = snapshotGcodeGenerator.CreateSnapshotGcode( 10, 10, 10, True, False, self.Extruder, "SavedCommand") def test_GetSnapshotGcode_Relative_RelativeCoordinates_AbsoluteExtruder_ZhopTooHigh( self): """Test snapshot gcode with relative stabilization, relative coordinates, absolute extruder, z is too high to hop, no retraction""" # test with relative coordinates, absolute extruder coordinates, z hop impossible (current z height will not allow this since it puts things outside of the bounds) # use relative coordinates for stabilizations self.Settings.CurrentStabilization().x_type = "relative" self.Settings.CurrentStabilization().x_relative = 50 #125 self.Settings.CurrentStabilization().y_type = "relative" self.Settings.CurrentStabilization().y_relative = 100 #200 self.Settings.CurrentSnapshot().retract_before_move = False snapshotGcodeGenerator = SnapshotGcodeGenerator( self.Settings, self.CreateOctoprintPrinterProfile()) # create snapshotGcode = snapshotGcodeGenerator.CreateSnapshotGcode( 10, 10, 200, True, False, self.Extruder, "SavedCommand") # verify the created gcode # this line should switch to absolute coordinates in prep for move self.assertTrue(snapshotGcode.GcodeCommands[0] == "G90") # this line should switch back to absolute coordinates self.assertTrue( snapshotGcode.GcodeCommands[1] == "G1 X125.000 Y200.000 F7200") # move back to the return position self.assertTrue( snapshotGcode.GcodeCommands[2] == "G1 X10.000 Y10.000 F7200") # change to relative coordinates self.assertTrue(snapshotGcode.GcodeCommands[3] == "G91") # the saved command self.assertTrue(snapshotGcode.GcodeCommands[4] == "SavedCommand") # verify the return commands self.assertTrue( snapshotGcode.ReturnCommands()[0] == "G1 X10.000 Y10.000 F7200") self.assertTrue(snapshotGcode.ReturnCommands()[1] == "G91") self.assertTrue(snapshotGcode.ReturnCommands()[2] == "SavedCommand") # verify the snapshot commands self.assertTrue(snapshotGcode.SnapshotCommands()[0] == "G90") self.assertTrue(snapshotGcode.SnapshotCommands()[1] == "G1 X125.000 Y200.000 F7200") # verify the indexes of the generated gcode self.assertTrue(snapshotGcode.SnapshotIndex == 1) self.assertTrue(snapshotGcode.EndIndex() == 4) # verify the return coordinates self.assertTrue(snapshotGcode.ReturnX == 10) self.assertTrue(snapshotGcode.ReturnY == 10) self.assertTrue(snapshotGcode.ReturnZ == 200)
def setUp(self): self.Settings = OctolapseSettings(NamedTemporaryFile().name) self.Extruder = Extruder(self.Settings)
class TestPosition(unittest.TestCase): 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() def tearDown(self): del self.Commands del self.Settings @staticmethod def create_octolapse_printer_profile(): return { "volume": { "custom_box": False, "width": 250, "depth": 200, "height": 200 } } def test_PositionError(self): """Test the IsInBounds function to make sure the program will not attempt to operate after being told to move out of bounds. """ position = Position(self.Settings, self.OctoprintPrinterProfile, False) # Initial test, should return false without any coordinates self.assertFalse(position.has_position_error()) self.assertIsNone(position.position_error()) # home the axis and test position.update("G28") self.assertFalse(position.has_position_error()) self.assertIsNone(position.position_error()) # X axis tests # reset, set relative extruder and absolute xyz, home the axis and test again position.reset() position.update("M83") position.update("G90") position.update("G28") self.assertFalse(position.has_position_error()) self.assertIsNone(position.position_error()) # move out of bounds min position.update("G0 x-0.0001") self.assertTrue(position.has_position_error()) self.assertTrue(position.position_error() is not None) # move back in bounds position.update("G0 x0.0") self.assertFalse(position.has_position_error()) self.assertIsNone(position.position_error()) # move to middle position.update("G0 x125") self.assertFalse(position.has_position_error()) self.assertIsNone(position.position_error()) # move to max position.update("G0 x250") self.assertFalse(position.has_position_error()) self.assertIsNone(position.position_error()) # move out of bounds max position.update("G0 x250.0001") self.assertTrue(position.has_position_error()) self.assertTrue(position.position_error() is not None) # Y axis tests # reset, set relative extruder and absolute xyz, home the axis and test again position.reset() position.update("M83") position.update("G90") position.update("G28") self.assertFalse(position.has_position_error()) self.assertIsNone(position.position_error()) # move out of bounds min position.update("G0 y-0.0001") self.assertTrue(position.has_position_error()) self.assertTrue(position.position_error() is not None) # move back in bounds position.update("G0 y0.0") self.assertFalse(position.has_position_error()) self.assertIsNone(position.position_error()) # move to middle position.update("G0 y100") self.assertFalse(position.has_position_error()) self.assertIsNone(position.position_error()) # move to max position.update("G0 y200") self.assertFalse(position.has_position_error()) self.assertIsNone(position.position_error()) # move out of bounds max position.update("G0 y200.0001") self.assertTrue(position.has_position_error()) self.assertTrue(position.position_error() is not None) # Z axis tests # reset, home the axis and test again # reset, set relative extruder and absolute xyz, home the axis and test again position.reset() position.update("M83") position.update("G90") position.update("G28") self.assertFalse(position.has_position_error()) self.assertIsNone(position.position_error()) # move out of bounds min position.update("G0 z-0.0001") self.assertTrue(position.has_position_error()) self.assertTrue(position.position_error() is not None) # move back in bounds position.update("G0 z0.0") self.assertFalse(position.has_position_error()) self.assertIsNone(position.position_error()) # move to middle position.update("G0 z100") self.assertFalse(position.has_position_error()) self.assertIsNone(position.position_error()) # move to max position.update("G0 z200") self.assertFalse(position.has_position_error()) self.assertIsNone(position.position_error()) # move out of bounds max position.update("G0 z200.0001") self.assertTrue(position.has_position_error()) self.assertTrue(position.position_error() is not None) def test_reset(self): """Test init state.""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) # reset all initialized vars to something else position.update("G28") position.update("G0 X1 Y1 Z1") # reset position.reset() # test initial state self.assertEqual(len(position.Positions), 0) self.assertIsNone(position.SavedPosition) def test_Home(self): """Test the home command. Make sure the position is set to 0,0,0 after the home.""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) position.update("G28") self.assertEqual(position.x(), 0) self.assertTrue(position.get_position().XHomed) self.assertEqual(position.y(), 0) self.assertTrue(position.get_position().YHomed) self.assertEqual(position.z(), 0) self.assertTrue(position.get_position().ZHomed) self.assertTrue(position.has_homed_position()) position.reset() position.update("G28 X") self.assertEqual(position.x(), 0) self.assertTrue(position.get_position().XHomed) self.assertIsNone(position.y()) self.assertFalse(position.get_position().YHomed) self.assertIsNone(position.z()) self.assertFalse(position.get_position().ZHomed) self.assertFalse(position.has_homed_position()) position.reset() position.update("G28 Y") self.assertIsNone(position.x()) self.assertFalse(position.get_position().XHomed) self.assertEqual(position.y(), 0) self.assertTrue(position.get_position().YHomed) self.assertIsNone(position.z()) self.assertFalse(position.get_position().ZHomed) self.assertFalse(position.has_homed_position()) position.reset() position.update("G28 Z") self.assertIsNone(position.x()) self.assertFalse(position.get_position().XHomed) self.assertIsNone(position.y()) self.assertFalse(position.get_position().YHomed) self.assertEqual(position.z(), 0) self.assertTrue(position.get_position().ZHomed) self.assertFalse(position.has_homed_position()) position.reset() position.update("G28 Z X Y") self.assertEqual(position.x(), 0) self.assertTrue(position.get_position().XHomed) self.assertEqual(position.y(), 0) self.assertTrue(position.get_position().YHomed) self.assertEqual(position.z(), 0) self.assertTrue(position.get_position().ZHomed) self.assertTrue(position.has_homed_position()) position.reset() position.update("g28") position.update("g1 x0 y0 z0") # here we have seen the upded coordinates, but we do not know the position self.assertEqual(position.x(), 0) self.assertTrue(position.get_position().XHomed) self.assertEqual(position.y(), 0) self.assertTrue(position.get_position().YHomed) self.assertEqual(position.z(), 0) self.assertTrue(position.get_position().ZHomed) # give it another position, now we have homed axis with a known position position.update("g1 x0 y0 z0") self.assertEqual(position.x(), 0) self.assertTrue(position.get_position().XHomed) self.assertEqual(position.y(), 0) self.assertTrue(position.get_position().YHomed) self.assertEqual(position.z(), 0) self.assertTrue(position.get_position().ZHomed) self.assertTrue(position.has_homed_position()) 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("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) def test_UpdatePosition_noforce(self): """Test the UpdatePosition function with the force option set to true.""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) # no homed axis position.update_position(x=0, y=0, z=0, e=0) self.assertIsNone(position.x()) self.assertIsNone(position.y()) self.assertIsNone(position.z()) self.assertIsNone(position.e(), 0) # set homed axis, test absolute position (default) position.update("G28") position.update_position(x=0, y=0, z=0) self.assertEqual(position.x(), 0) self.assertEqual(position.y(), 0) self.assertEqual(position.z(), 0) self.assertEqual(position.e(), 0) # update absolute position position.update_position(x=1, y=2, z=3) self.assertEqual(position.x(), 1) self.assertEqual(position.y(), 2) self.assertEqual(position.z(), 3) self.assertEqual(position.e(), 0) # set relative position position.update("G91") position.update_position(x=1, y=1, z=1) self.assertEqual(position.x(), 2) self.assertEqual(position.y(), 3) self.assertEqual(position.z(), 4) self.assertEqual(position.e(), 0) # set extruder absolute position.update("M82") position.update_position(e=100) self.assertEqual(position.x(), 2) self.assertEqual(position.y(), 3) self.assertEqual(position.z(), 4) self.assertEqual(position.e(), 100) position.update_position(e=-10) self.assertEqual(position.x(), 2) self.assertEqual(position.y(), 3) self.assertEqual(position.z(), 4) self.assertEqual(position.e(), -10) # set extruder relative position.update("M83") position.update_position(e=20) self.assertEqual(position.x(), 2) self.assertEqual(position.y(), 3) self.assertEqual(position.z(), 4) self.assertEqual(position.e(), 10) position.update_position(e=-1) self.assertEqual(position.x(), 2) self.assertEqual(position.y(), 3) self.assertEqual(position.z(), 4) self.assertEqual(position.e(), 9) 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) 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("G28") # set absolute mode with G90 position.update("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("g91") # update the position to 20 (relative) position.update_position(e=20) self.assertEqual(position.e(), 30) def test_G90InfluencesExtruder_Update(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("G28") # set absolute mode with G90 position.update("g90") # update the position to 10 (absolute) position.update("G1 E10.0") self.assertEqual(position.e(), 10) # update the position to 10 again (absolute) to make sure we are in absolute # coordinates. position.update("G1 E10.0") self.assertEqual(position.e(), 10) # set relative mode with G90 position.update("g91") # update the position to 20 (relative) position.update("G1 E20.0") self.assertEqual(position.e(), 30) def test_Update(self): """Test the Update() function, which accepts gcode and updates the current position state and extruder state.""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) # no homed axis position.update("G1 x100 y200 z300") self.assertIsNone(position.x()) self.assertIsNone(position.y()) self.assertIsNone(position.z()) # set relative extruder and absolute xyz, home axis and update absolute position position.update("M83") position.update("G90") position.update("G28") position.update("G1 x100 y200 z150") self.assertEqual(position.x(), 100) self.assertEqual(position.y(), 200) self.assertEqual(position.z(), 150) # move again and retest position.update("G1 x101 y199 z151") self.assertEqual(position.x(), 101) self.assertEqual(position.y(), 199) self.assertEqual(position.z(), 151) # switch to relative and update position position.update("G91") position.update("G1 x-1 y-1 z1.0") self.assertEqual(position.x(), 100) self.assertEqual(position.y(), 198) self.assertEqual(position.z(), 152) # move again and retest position.update("G1 x-99 y-196 z-149.0") self.assertEqual(position.x(), 1) self.assertEqual(position.y(), 2) self.assertEqual(position.z(), 3) # go back to absolute and move to origin position.update("G90") position.update("G1 x0 y0 z0.0") self.assertEqual(position.x(), 0) self.assertEqual(position.y(), 0) self.assertEqual(position.z(), 0) # G92 Test Set Position def test_G92SetPosition(self): """Test the G92 command, settings the position.""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) # no homed axis position.update("G92 x10 y20 z30") self.assertIsNone(position.x()) self.assertIsNone(position.y()) self.assertIsNone(position.z()) # set homed axis, absolute coordinates, and set position position.update("G28") position.update("G90") position.update("G1 x100 y200 z150") position.update("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("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("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("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) # G92 Test Absolute Movement 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("G28") position.update("G90") position.update("G1 x100 y200 z150") position.update("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("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("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) # G92 Test Relative Movement 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("G28") position.update("G91") position.update("G1 x100 y200 z150") position.update("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("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("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("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) def test_HeightAndLayerChanges(self): """Test the height and layer changes.""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) # test initial state self.assertIsNone(position.height()) self.assertIsNone(position.layer(), None) self.assertFalse(position.is_layer_change()) # check without homed axis position.update("G1 x0 y0 z0.20000 e1") self.assertEqual(position.height(), 0) self.assertEqual(position.layer(), 0) self.assertFalse(position.is_layer_change()) # set homed axis, absolute xyz coordinates, relative extruder coordinates and check height and layer position.update("M83") position.update("G90") position.update("G28") self.assertEqual(position.height(), 0) self.assertEqual(position.layer(), 0) self.assertFalse(position.is_layer_change()) # move without extruding, height and layer should not change position.update("G1 x100 y200 z150") self.assertEqual(position.height(), 0) self.assertEqual(position.layer(), 0) self.assertFalse(position.is_layer_change()) # move to origin, height and layer stuff should stay the same position.update("G1 x0 y0 z0") self.assertEqual(position.height(), 0) self.assertEqual(position.layer(), 0) self.assertFalse(position.is_layer_change()) # extrude, height change! position.update("G1 x0 y0 z0 e1") self.assertEqual(position.height(), 0) self.assertEqual(position.layer(), 1) self.assertTrue(position.is_layer_change()) # extrude higher, update layer., this will get rounded to 0.2 position.update("G1 x0 y0 z0.1999 e1") self.assertEqual(position.height(), 0.2) self.assertEqual(position.layer(), 2) self.assertTrue(position.is_layer_change()) # extrude just slightly higher, but with rounding on the same layer position.update("G1 x0 y0 z0.20000 e1") self.assertEqual(position.height(), .2) self.assertEqual(position.layer(), 2) self.assertFalse(position.is_layer_change()) # extrude again on same layer - Height Previous should now be updated, and # IsLayerChange should be false position.update("G1 x0 y0 z0.20000 e1") self.assertEqual(position.height(), .2) self.assertEqual(position.layer(), 2) self.assertFalse(position.is_layer_change()) # extrude again on same layer - No changes position.update("G1 x0 y0 z0.20000 e1") self.assertEqual(position.height(), .2) self.assertEqual(position.layer(), 2) self.assertFalse(position.is_layer_change()) # extrude below the current layer - No changes position.update("G1 x0 y0 z0.00000 e1") self.assertEqual(position.height(), .2) self.assertEqual(position.layer(), 2) self.assertFalse(position.is_layer_change()) # extrude up higher and change the height/layer. Should never happen, but # it's an interesting test case position.update("G1 x0 y0 z0.60000 e1") self.assertEqual(position.height(), .6) self.assertEqual(position.layer(), 3) self.assertTrue(position.is_layer_change()) # extrude up again position.update("G1 x0 y0 z0.65000 e1") self.assertEqual(position.height(), .65) self.assertEqual(position.layer(), 4) self.assertTrue(position.is_layer_change()) # extrude on previous layer position.update("G1 x0 y0 z0.60000 e1") self.assertEqual(position.height(), .65) self.assertEqual(position.layer(), 4) self.assertFalse(position.is_layer_change()) # extrude on previous layer again position.update("G1 x0 y0 z0.60000 e1") self.assertEqual(position.height(), .65) self.assertEqual(position.layer(), 4) self.assertFalse(position.is_layer_change()) # move up but do not extrude position.update("G1 x0 y0 z0.70000") self.assertEqual(position.height(), .65) self.assertEqual(position.layer(), 4) self.assertFalse(position.is_layer_change()) # move up but do not extrude a second time position.update("G1 x0 y0 z0.80000") self.assertEqual(position.height(), .65) self.assertEqual(position.layer(), 4) self.assertFalse(position.is_layer_change()) # extrude at a different height position.update("G1 x0 y0 z0.80000 e.1") position.update("G1 x0 y0 z0.85000 e.1") self.assertEqual(.85, position.height()) self.assertEqual(6, position.layer()) self.assertTrue(position.is_layer_change()) # M82 and M83 - Test extruder movement 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("M83") # test movement previous_pos = Pos(self.Settings.current_printer(), self.OctoprintPrinterProfile, position.get_position()) position.update("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("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("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("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("M83") position.update("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("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("G0 e-2.2") self.assertEqual(position.e(), 0) self.assertEqual(position.e_relative_pos(previous_pos), 2.2) def test_zHop(self): """Test zHop detection.""" # set zhop distance self.Settings.current_printer().z_hop = .5 position = Position(self.Settings, self.OctoprintPrinterProfile, False) # test initial state self.assertFalse(position.is_zhop()) # check without homed axis position.update("G1 x0 y0 z0") self.assertFalse(position.is_zhop()) position.update("G1 x0 y0 z0.5") self.assertFalse(position.is_zhop()) # set relative extruder, absolute xyz, home axis, check again position.update("M83") position.update("G90") position.update("G28") self.assertFalse(position.is_zhop()) # Position reports as NotHomed (misnomer, need to replace), needs to get # coordinates position.update("G1 x0 y0 z0") # Move up without extrude, this is not a zhop since we haven't extruded # anything! position.update("g0 z0.5") self.assertFalse(position.is_zhop()) # move back down to 0 and extrude position.update("g0 z0 e1") self.assertFalse(position.is_zhop()) # Move up without extrude, this should trigger zhop start position.update("g0 z0.5") self.assertTrue(position.is_zhop()) # move below zhop threshold position.update("g0 z0.3") self.assertFalse(position.is_zhop()) # move right up to zhop without going over, we are within the rounding error position.update("g0 z0.4999") self.assertTrue(position.is_zhop()) # Extrude on z5 position.update("g0 z0.5 e1") self.assertFalse(position.is_zhop()) # partial z lift, , we are within the rounding error position.update("g0 z0.9999") self.assertTrue(position.is_zhop()) # Still hopped! position.update("g0 z1") self.assertTrue(position.is_zhop()) # test with extrusion start at 1.5 position.update("g0 z1.5 e1") self.assertFalse(position.is_zhop()) # test with extrusion at 2 position.update("g0 z2 e1") self.assertFalse(position.is_zhop()) # zhop position.update("g0 z2.5 e0") self.assertTrue(position.is_zhop()) position.update("no-command") self.assertTrue(position.is_zhop()) # todo: IsAtCurrent/PreviousPosition tests 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("M83") position.update("G90") position.update("G28") position.update("G1 X119.915 Y113.338 Z2.1 F7200") self.assertTrue(position.is_at_current_position(119.91, 113.34, 2.1)) position.update("g0 x120 y121 z2.1") self.assertTrue(position.is_at_previous_position(119.91, 113.34, 2.1)) @unittest.skip("Not yet implemented") def test_extruder_axis_default_mode_relative(self): # test e_axis_default_mode = 'relative' raise NotImplementedError @unittest.skip("Not yet implemented") def test_extruder_axis_default_mode_absolute(self): # test e_axis_default_mode = 'absolute' raise NotImplementedError @unittest.skip("Not yet implemented") def test_extruder_axis_default_mode_require_explicit(self): # test e_axis_default_mode = 'require-explicit' raise NotImplementedError @unittest.skip("Not yet implemented") def test_xyz_axis_default_mode_relative(self): # test xyz_axes_default_mode = 'relative' raise NotImplementedError @unittest.skip("Not yet implemented") def test_xyz_axis_default_mode_absolute(self): # test xyz_axes_default_mode = 'absolute' raise NotImplementedError @unittest.skip("Not yet implemented") def test_xyz_axis_default_mode_require_explicit(self): # test xyz_axes_default_mode = 'require-explicit' raise NotImplementedError @unittest.skip("Not yet implemented") def test_g90_influences_extruder_use_octoprint_settings(self): # test g90_influences_extruder = 'use-octoprint-settings' raise NotImplementedError @unittest.skip("Not yet implemented") def test_g90_influences_extruder_true(self): # test g90_influences_extruder = 'true' raise NotImplementedError @unittest.skip("Not yet implemented") def test_g90_influences_extruder_false(self): # test g90_influences_extruder = 'false' raise NotImplementedError @unittest.skip("Not yet implemented") def test_priming_height(self): # test the priming height > 0 raise NotImplementedError @unittest.skip("Not yet implemented") def test_priming_height_0(self): # test the priming height = 0 raise NotImplementedError
def setUp(self): self.Settings = OctolapseSettings(NamedTemporaryFile().name) self.PrinterTolerance = 0.0
def setUp(self): self.Commands = Commands() self.Settings = OctolapseSettings("c:\\temp\\octolapse.log") self.OctoprintPrinterProfile = self.CreateOctoprintPrinterProfile()
def setUp(self): self.Settings = OctolapseSettings("c:\\test\\") self.OctoprintPrinterProfile = self.CreateOctoprintPrinterProfile()
class Test_TimerTrigger(unittest.TestCase): def setUp(self): self.Settings = OctolapseSettings("c:\\test\\") self.OctoprintPrinterProfile = self.CreateOctoprintPrinterProfile() def tearDown(self): del self.Settings del self.OctoprintPrinterProfile def CreateOctoprintPrinterProfile(self): return dict(volume=dict( width=250, depth=200, height=200, formFactor="Not A Circle", custom_box=False, )) def test_TimerTrigger(self): """Test the timer trigger""" # use a short trigger time so that the test doesn't take too long self.Settings.CurrentSnapshot().timer_trigger_seconds = 2 position = Position(self.Settings, self.OctoprintPrinterProfile, False) trigger = TimerTrigger(self.Settings) trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, None, None, None, None, None, None) #Ignore extruder trigger.RequireZHop = False # no zhop required trigger.HeightIncrement = 0 # Trigger on any height change # test initial state self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == False) # set interval time to 0, send another command and test again (should not trigger, no homed axis) trigger.IntervalSeconds = 0 position.Update("g0 x0 y0 z.2 e1") trigger.Update(position) self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == False) # Home all axis and try again with interval seconds 1 - should not trigger since the timer will start after the home command trigger.IntervalSeconds = 2 position.Update("g28") trigger.Update(position) self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == False) # send another command and try again, should not trigger cause we haven't waited 2 seconds yet position.Update("g0 x0 y0 z.2 e1") trigger.Update(position) self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == False) # Set the last trigger time to 1 before the previous LastTrigger time(equal to interval seconds), should not trigger trigger.TriggerStartTime = time.time() - 1.01 position.Update("g0 x0 y0 z.2 e1") trigger.Update(position) self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == False) # Set the last trigger time to 1 before the previous LastTrigger time(equal to interval seconds), should trigger trigger.TriggerStartTime = time.time() - 2.01 position.Update("g0 x0 y0 z.2 e1") trigger.Update(position) self.assertTrue(trigger.IsTriggered == True) self.assertTrue(trigger.IsWaiting == False) def test_TimerTrigger_ExtruderTriggers(self): """Test All Extruder Triggers""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) # home the axis position.Update("G28") trigger = TimerTrigger(self.Settings) trigger.IntervalSeconds = 1 trigger.RequireZHop = False # no zhop required #Reset the extruder position.Extruder.Reset() position.Extruder.IsPrimed = False trigger.IsWaiting = True # Try on extruding start - previous position not homed, do not trigger trigger.ExtruderTriggers = ExtruderTriggers(True, None, None, None, None, None, None, None, None, None) position.Extruder.IsExtrudingStart = True trigger.TriggerStartTime = time.time() - 1.01 trigger.Update(position) self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == True) # send another command, now the previous state has been homed, should trigger position.Update("AnotherCommandNowPreviousHomed") position.Extruder.IsExtrudingStart = True # set is extruding start, wont be set by the above command! trigger.Update(position) self.assertTrue(trigger.IsTriggered == True) self.assertTrue(trigger.IsWaiting == False) #Reset the extruder position.Extruder.Reset() position.Extruder.IsPrimed = False trigger.IsWaiting = True # try out on extruding trigger.ExtruderTriggers = ExtruderTriggers(None, True, None, None, None, None, None, None, None, None) position.Extruder.IsExtruding = True trigger.TriggerStartTime = time.time() - 1.01 trigger.Update(position) self.assertTrue(trigger.IsTriggered == True) self.assertTrue(trigger.IsWaiting == False) #Reset the extruder position.Extruder.Reset() position.Extruder.IsPrimed = False trigger.IsWaiting = True # try out on primed trigger.ExtruderTriggers = ExtruderTriggers(None, None, True, None, None, None, None, None, None, None) position.Extruder.IsPrimed = True trigger.TriggerStartTime = time.time() - 1.01 trigger.Update(position) self.assertTrue(trigger.IsTriggered == True) self.assertTrue(trigger.IsWaiting == False) #Reset the extruder position.Extruder.Reset() position.Extruder.IsPrimed = False trigger.IsWaiting = True # try out on retracting start trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, True, None, None, None, None, None, None) position.Extruder.IsRetractingStart = True trigger.TriggerStartTime = time.time() - 1.01 trigger.Update(position) self.assertTrue(trigger.IsTriggered == True) self.assertTrue(trigger.IsWaiting == False) #Reset the extruder position.Extruder.Reset() position.Extruder.IsPrimed = False trigger.IsWaiting = True # try out on retracting trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, True, None, None, None, None, None) position.Extruder.IsRetracting = True trigger.TriggerStartTime = time.time() - 1.01 trigger.Update(position) self.assertTrue(trigger.IsTriggered == True) self.assertTrue(trigger.IsWaiting == False) #Reset the extruder position.Extruder.Reset() position.Extruder.IsPrimed = False trigger.IsWaiting = True # try out on partially retracted trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, None, True, None, None, None, None) position.Extruder.IsPartiallyRetracted = True trigger.TriggerStartTime = time.time() - 1.01 trigger.Update(position) self.assertTrue(trigger.IsTriggered == True) self.assertTrue(trigger.IsWaiting == False) #Reset the extruder position.Extruder.Reset() position.Extruder.IsPrimed = False trigger.IsWaiting = True # try out on retracted trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, None, None, True, None, None, None) position.Extruder.IsRetracted = True trigger.TriggerStartTime = time.time() - 1.01 trigger.Update(position) self.assertTrue(trigger.IsTriggered == True) self.assertTrue(trigger.IsWaiting == False) #Reset the extruder position.Extruder.Reset() position.Extruder.IsPrimed = False trigger.IsWaiting = True # try out on detracting Start trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, None, None, None, True, None, None) position.Extruder.IsDetractingStart = True trigger.TriggerStartTime = time.time() - 1.01 trigger.Update(position) self.assertTrue(trigger.IsTriggered == True) self.assertTrue(trigger.IsWaiting == False) #Reset the extruder position.Extruder.Reset() position.Extruder.IsPrimed = False trigger.IsWaiting = True # try out on detracting Start trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, None, None, None, None, True, None) position.Extruder.IsDetracting = True trigger.TriggerStartTime = time.time() - 1.01 trigger.Update(position) self.assertTrue(trigger.IsTriggered == True) self.assertTrue(trigger.IsWaiting == False) #Reset the extruder position.Extruder.Reset() position.Extruder.IsPrimed = False trigger.IsWaiting = True # try out on detracting Start trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, None, None, None, None, None, True) position.Extruder.IsDetracted = True trigger.TriggerStartTime = time.time() - 1.01 trigger.Update(position) self.assertTrue(trigger.IsTriggered == True) self.assertTrue(trigger.IsWaiting == False) def test_TimerTrigger_ExtruderTriggerWait(self): """Test wait on extruder""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) # home the axis position.Update("G28") trigger = TimerTrigger(self.Settings) trigger.RequireZHop = False # no zhop required trigger.IntervalSeconds = 1 #Reset the extruder position.Extruder.Reset() position.Extruder.IsPrimed = False trigger.IsWaiting = False # Use on extruding start for this test. trigger.ExtruderTriggers = ExtruderTriggers(True, None, None, None, None, None, None, None, None, None) position.Extruder.IsExtrudingStart = False trigger.TriggerStartTime = time.time() - 1.01 # will not wait or trigger because the previous position state was not homed trigger.Update(position) self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == False) # send another command and try again position.Update("PreviousPositionIsNowHomed") trigger.Update(position) self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == True) # update again with no change trigger.Update(position) self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == True) # set the trigger and try again position.Extruder.IsExtrudingStart = True trigger.Update(position) self.assertTrue(trigger.IsTriggered == True) self.assertTrue(trigger.IsWaiting == False) def test_TimerTrigger_LayerChange_ZHop(self): """Test the layer trigger for layer changes triggers""" self.Settings.CurrentSnapshot().timer_trigger_require_zhop = True self.Settings.CurrentPrinter().z_hop = .5 position = Position(self.Settings, self.OctoprintPrinterProfile, False) trigger = TimerTrigger(self.Settings) trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, None, None, None, None, None, None) #Ignore extruder trigger.IntervalSeconds = 1 # test initial state self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == False) # send commands that normally would trigger a layer change, but without all axis homed. position.Update("g0 x0 y0 z.2 e1") trigger.Update(position) self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == False) # Home all axis and try again, wait on zhop position.Update("g28") trigger.Update(position) self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == False) position.Update("g0 x0 y0 z.2 e1") trigger.TriggerStartTime = time.time() - 1.01 trigger.Update(position) self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == True) # try zhop position.Update("g0 x0 y0 z.7 ") trigger.Update(position) self.assertTrue(trigger.IsTriggered == True) self.assertTrue(trigger.IsWaiting == False) # extrude on current layer, no trigger (wait on zhop) position.Update("g0 x0 y0 z.7 e1") trigger.TriggerStartTime = time.time() - 1.01 trigger.Update(position) self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == True) # do not extrude on current layer, still waiting position.Update("g0 x0 y0 z.7 ") trigger.Update(position) self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == True) # partial hop, but close enough based on our printer measurement tolerance (0.005) position.Update("g0 x0 y0 z1.1999") trigger.Update(position) self.assertTrue(trigger.IsTriggered == True) self.assertTrue(trigger.IsWaiting == False) # creat wait state position.Update("g0 x0 y0 z1.3 e1") trigger.TriggerStartTime = time.time() - 1.01 trigger.Update(position) self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == True) # move down (should never happen, should behave properly anyway) position.Update("g0 x0 y0 z.8") trigger.Update(position) self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == True) # move back up to current layer (should NOT trigger zhop) position.Update("g0 x0 y0 z1.3") trigger.Update(position) self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == True) # move up a bit, not enough to trigger zhop position.Update("g0 x0 y0 z1.79749") trigger.Update(position) self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == True) # move up a bit, just enough to trigger zhop position.Update("g0 x0 y0 z1.79751") trigger.Update(position) self.assertTrue(trigger.IsTriggered == True) self.assertTrue(trigger.IsWaiting == False)
class TestSnapshotGcode(unittest.TestCase): def setUp(self): self.Settings = OctolapseSettings(NamedTemporaryFile().name) self.OctoprintPrinterProfile = self.create_octoprint_printer_profile() printer = get_printer_profile() self.Settings.printers.update({printer["guid"]: Printer(printer=printer)}) self.Settings.current_printer_profile_guid = printer["guid"] self.Extruder = Extruder(self.Settings) self.Position = Position(self.Settings, self.OctoprintPrinterProfile, False) # set starting position def tearDown(self): del self.Settings del self.Extruder @staticmethod def create_octoprint_printer_profile(): return dict( volume=dict( width=250, depth=200, height=200, formFactor="Not A Circle", custom_box=False, ) ) def test_GetSnapshotPosition_Absolute(self): """Test getting absolute snapshot positions for x and y""" # 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()) # get the coordinates and test coords = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coords["X"] == 10 and coords["Y"] == 20) # get the coordinates and test coords = snapshot_gcode_generator.get_snapshot_position(1, 1) self.assertTrue(coords["X"] == 10 and coords["Y"] == 20) # get the coordinates and test coords = snapshot_gcode_generator.get_snapshot_position(100, 100) self.assertTrue(coords["X"] == 10 and coords["Y"] == 20) def test_GetSnapshotPosition_AbsolutePath(self): """Test getting absolute path snapshot positions for x and y""" # adjust the settings for absolute position and create the snapshot gcode generator self.Settings.current_stabilization().x_type = "fixed_path" self.Settings.current_stabilization().x_fixed_path = "0,1,2,3,4,5" self.Settings.current_stabilization().y_type = "fixed_path" self.Settings.current_stabilization().y_fixed_path = "5,4,3,2,1,0" # test with no loop self.Settings.current_stabilization().x_fixed_path_loop = False self.Settings.current_stabilization().x_fixed_path_invert_loop = False self.Settings.current_stabilization().y_fixed_path_loop = False self.Settings.current_stabilization().y_fixed_path_invert_loop = False snapshot_gcode_generator = SnapshotGcodeGenerator( self.Settings, self.create_octoprint_printer_profile()) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 0 and coordinates["Y"] == 5) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 1 and coordinates["Y"] == 4) coordinates = snapshot_gcode_generator.get_snapshot_position(1, 0) self.assertTrue(coordinates["X"] == 2 and coordinates["Y"] == 3) coordinates = snapshot_gcode_generator.get_snapshot_position(1, 1) self.assertTrue(coordinates["X"] == 3 and coordinates["Y"] == 2) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 1) self.assertTrue(coordinates["X"] == 4 and coordinates["Y"] == 1) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 5 and coordinates["Y"] == 0) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 5 and coordinates["Y"] == 0) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 5 and coordinates["Y"] == 0) # test with loop, no invert self.Settings.current_stabilization().x_fixed_path_loop = True self.Settings.current_stabilization().x_fixed_path_invert_loop = False self.Settings.current_stabilization().y_fixed_path_loop = True self.Settings.current_stabilization().y_fixed_path_invert_loop = False snapshot_gcode_generator = SnapshotGcodeGenerator( self.Settings, self.create_octoprint_printer_profile()) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 0 and coordinates["Y"] == 5) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 1 and coordinates["Y"] == 4) coordinates = snapshot_gcode_generator.get_snapshot_position(1, 0) self.assertTrue(coordinates["X"] == 2 and coordinates["Y"] == 3) coordinates = snapshot_gcode_generator.get_snapshot_position(1, 1) self.assertTrue(coordinates["X"] == 3 and coordinates["Y"] == 2) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 1) self.assertTrue(coordinates["X"] == 4 and coordinates["Y"] == 1) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 5 and coordinates["Y"] == 0) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 0 and coordinates["Y"] == 5) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 1 and coordinates["Y"] == 4) # test with loop and invert self.Settings.current_stabilization().x_fixed_path_loop = True self.Settings.current_stabilization().x_fixed_path_invert_loop = True self.Settings.current_stabilization().y_fixed_path_loop = True self.Settings.current_stabilization().y_fixed_path_invert_loop = True snapshot_gcode_generator = SnapshotGcodeGenerator( self.Settings, self.create_octoprint_printer_profile()) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 0 and coordinates["Y"] == 5) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 1 and coordinates["Y"] == 4) coordinates = snapshot_gcode_generator.get_snapshot_position(1, 0) self.assertTrue(coordinates["X"] == 2 and coordinates["Y"] == 3) coordinates = snapshot_gcode_generator.get_snapshot_position(1, 1) self.assertTrue(coordinates["X"] == 3 and coordinates["Y"] == 2) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 1) self.assertTrue(coordinates["X"] == 4 and coordinates["Y"] == 1) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 5 and coordinates["Y"] == 0) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 4 and coordinates["Y"] == 1) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 3 and coordinates["Y"] == 2) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 2 and coordinates["Y"] == 3) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 1 and coordinates["Y"] == 4) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 0 and coordinates["Y"] == 5) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 1 and coordinates["Y"] == 4) def test_GetSnapshotPosition_BedRelative(self): """Test getting bed relative snapshot positions for x and y""" # adjust the settings for absolute position and create the snapshot gcode generator self.Settings.current_stabilization().x_type = "relative" self.Settings.current_stabilization().x_relative = 0 self.Settings.current_stabilization().y_type = "relative" self.Settings.current_stabilization().y_relative = 100 snapshot_gcode_generator = SnapshotGcodeGenerator( self.Settings, self.create_octoprint_printer_profile()) # get the coordinates and test coords = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coords["X"] == 0 and coords["Y"] == 200) # get the coordinates and test coords = snapshot_gcode_generator.get_snapshot_position(1, 1) self.assertTrue(coords["X"] == 0 and coords["Y"] == 200) # get the coordinates and test coords = snapshot_gcode_generator.get_snapshot_position(100, 100) self.assertTrue(coords["X"] == 0 and coords["Y"] == 200) def test_GetSnapshotPosition_BedRelativePath(self): """Test getting bed relative path snapshot positions for x and y""" # adjust the settings for absolute position and create the snapshot gcode generator self.Settings.current_stabilization().x_type = "relative_path" self.Settings.current_stabilization().x_relative_path = "0,25,50,75,100" self.Settings.current_stabilization().y_type = "relative_path" self.Settings.current_stabilization().y_relative_path = "100,75,50,25,0" # test with no loop self.Settings.current_stabilization().x_relative_path_loop = False self.Settings.current_stabilization().x_relative_path_invert_loop = False self.Settings.current_stabilization().y_relative_path_loop = False self.Settings.current_stabilization().y_relative_path_invert_loop = False snapshot_gcode_generator = SnapshotGcodeGenerator( self.Settings, self.create_octoprint_printer_profile()) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 0 and coordinates["Y"] == 200) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 62.5 and coordinates["Y"] == 150) coordinates = snapshot_gcode_generator.get_snapshot_position(1, 0) self.assertTrue(coordinates["X"] == 125 and coordinates["Y"] == 100) coordinates = snapshot_gcode_generator.get_snapshot_position(1, 1) self.assertTrue(coordinates["X"] == 187.5 and coordinates["Y"] == 50) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 1) self.assertTrue(coordinates["X"] == 250 and coordinates["Y"] == 0) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 250 and coordinates["Y"] == 0) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 250 and coordinates["Y"] == 0) # test with loop, no invert self.Settings.current_stabilization().x_relative_path_loop = True self.Settings.current_stabilization().x_relative_path_invert_loop = False self.Settings.current_stabilization().y_relative_path_loop = True self.Settings.current_stabilization().y_relative_path_invert_loop = False snapshot_gcode_generator = SnapshotGcodeGenerator( self.Settings, self.create_octoprint_printer_profile()) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 0 and coordinates["Y"] == 200) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 62.5 and coordinates["Y"] == 150) coordinates = snapshot_gcode_generator.get_snapshot_position(1, 0) self.assertTrue(coordinates["X"] == 125 and coordinates["Y"] == 100) coordinates = snapshot_gcode_generator.get_snapshot_position(1, 1) self.assertTrue(coordinates["X"] == 187.5 and coordinates["Y"] == 50) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 1) self.assertTrue(coordinates["X"] == 250 and coordinates["Y"] == 0) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 0 and coordinates["Y"] == 200) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 62.5 and coordinates["Y"] == 150) # test with loop and invert self.Settings.current_stabilization().x_relative_path_loop = True self.Settings.current_stabilization().x_relative_path_invert_loop = True self.Settings.current_stabilization().y_relative_path_loop = True self.Settings.current_stabilization().y_relative_path_invert_loop = True snapshot_gcode_generator = SnapshotGcodeGenerator( self.Settings, self.create_octoprint_printer_profile()) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 0 and coordinates["Y"] == 200) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 62.5 and coordinates["Y"] == 150) coordinates = snapshot_gcode_generator.get_snapshot_position(1, 0) self.assertTrue(coordinates["X"] == 125 and coordinates["Y"] == 100) coordinates = snapshot_gcode_generator.get_snapshot_position(1, 1) self.assertTrue(coordinates["X"] == 187.5 and coordinates["Y"] == 50) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 1) self.assertTrue(coordinates["X"] == 250 and coordinates["Y"] == 0) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 187.5 and coordinates["Y"] == 50) coordinates = snapshot_gcode_generator.get_snapshot_position(0, 0) self.assertTrue(coordinates["X"] == 125 and coordinates["Y"] == 100) 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) def test_GetSnapshotGcode_RelativePath_RelativeCoordinates_ExtruderAbsolute_ZHop_Retraction(self): # test with relative paths, absolute extruder coordinates, retract and z hop # use relative coordinates for stabilizations self.Settings.current_stabilization().x_type = "relative_path" self.Settings.current_stabilization().x_relative_path = "50,100" # 125,250 self.Settings.current_stabilization().x_relative_path_loop = False self.Settings.current_stabilization().x_relative_path_invert_loop = False self.Settings.current_stabilization().y_type = "relative_path" self.Settings.current_stabilization().y_relative_path = "50,100" # 100,200 self.Settings.current_stabilization().y_relative_path_loop = False self.Settings.current_stabilization().y_relative_path_invert_loop = False self.Settings.current_snapshot().retract_before_move = True snapshot_gcode_generator = SnapshotGcodeGenerator( self.Settings, self.create_octoprint_printer_profile()) snapshot_gcode = snapshot_gcode_generator.create_snapshot_gcode( 10, 10, 10, 3600, True, False, self.Extruder, 0.5, "SavedCommand") # verify the created gcode self.assertEqual(snapshot_gcode.GcodeCommands[0], "M83") self.assertEqual(snapshot_gcode.GcodeCommands[1], "G1 F4000") self.assertEqual(snapshot_gcode.GcodeCommands[2], "G1 E-2.000") self.assertEqual(snapshot_gcode.GcodeCommands[3], "G1 F6000") self.assertEqual(snapshot_gcode.GcodeCommands[4], "G1 Z0.500") self.assertEqual(snapshot_gcode.GcodeCommands[5], "G90") self.assertEqual(snapshot_gcode.GcodeCommands[6], "G1 F6000") self.assertEqual(snapshot_gcode.GcodeCommands[7], "G1 X125.000 Y100.000") self.assertEqual(snapshot_gcode.GcodeCommands[8], "M400") self.assertEqual(snapshot_gcode.GcodeCommands[9], "M114") self.assertEqual(snapshot_gcode.GcodeCommands[10], "G1 X10.000 Y10.000") self.assertEqual(snapshot_gcode.GcodeCommands[11], "G91") self.assertEqual(snapshot_gcode.GcodeCommands[12], "G1 F6000") self.assertEqual(snapshot_gcode.GcodeCommands[13], "G1 Z-0.500") self.assertEqual(snapshot_gcode.GcodeCommands[14], "G1 F3000") self.assertEqual(snapshot_gcode.GcodeCommands[15], "G1 E2.000") self.assertEqual(snapshot_gcode.GcodeCommands[16], "M82") self.assertEqual(snapshot_gcode.GcodeCommands[17], "G1 F3600") self.assertEqual(snapshot_gcode.GcodeCommands[18], "SAVEDCOMMAND") self.assertEqual(snapshot_gcode.GcodeCommands[19], "M400") self.assertEqual(snapshot_gcode.GcodeCommands[20], "M114") # verify the indexes of the generated gcode self.assertTrue(snapshot_gcode.SnapshotIndex == 9) self.assertTrue(snapshot_gcode.end_index() == 20) # verify the return coordinates self.assertTrue(snapshot_gcode.ReturnX == 10) self.assertTrue(snapshot_gcode.ReturnY == 10) self.assertTrue(snapshot_gcode.ReturnZ == 10) def test_GetSnapshotGcode_FixedPath_RelativeCoordinates_ExtruderAbsolute_ZHop_AlreadyRetracted(self): # test with relative paths, absolute extruder coordinates, retract and z hop # use relative coordinates for stabilizations self.Settings.current_stabilization().x_type = "fixed_path" self.Settings.current_stabilization().x_fixed_path = "50,100" # 125,250 self.Settings.current_stabilization().x_fixed_path_loop = False self.Settings.current_stabilization().x_fixed_path_invert_loop = False self.Settings.current_stabilization().y_type = "fixed_path" self.Settings.current_stabilization().y_fixed_path = "50,100" # 100,200 self.Settings.current_stabilization().y_fixed_path_loop = False self.Settings.current_stabilization().y_fixed_path_invert_loop = False self.Settings.current_snapshot().retract_before_move = True snapshot_gcode_generator = SnapshotGcodeGenerator( self.Settings, self.create_octoprint_printer_profile()) self.Extruder.is_retracted = lambda: True snapshot_gcode = snapshot_gcode_generator.create_snapshot_gcode( 100, 50, 0, 3600, True, False, self.Extruder, 0.5, "SavedCommand") # verify the created gcode self.assertEqual(snapshot_gcode.GcodeCommands[0], "G1 F6000") self.assertEqual(snapshot_gcode.GcodeCommands[1], "G1 Z0.500") self.assertEqual(snapshot_gcode.GcodeCommands[2], "G90") self.assertEqual(snapshot_gcode.GcodeCommands[3], "G1 F6000") self.assertEqual(snapshot_gcode.GcodeCommands[4], "G1 X50.000 Y50.000") self.assertEqual(snapshot_gcode.GcodeCommands[5], "M400") self.assertEqual(snapshot_gcode.GcodeCommands[6], "M114") self.assertEqual(snapshot_gcode.GcodeCommands[7], "G1 X100.000 Y50.000") self.assertEqual(snapshot_gcode.GcodeCommands[8], "G91") self.assertEqual(snapshot_gcode.GcodeCommands[9], "G1 F6000") self.assertEqual(snapshot_gcode.GcodeCommands[10], "G1 Z-0.500") self.assertEqual(snapshot_gcode.GcodeCommands[11], "G1 F3600") self.assertEqual(snapshot_gcode.GcodeCommands[12], "SAVEDCOMMAND") self.assertEqual(snapshot_gcode.GcodeCommands[13], "M400") self.assertEqual(snapshot_gcode.GcodeCommands[14], "M114") # verify the indexes of the generated gcode self.assertEqual(snapshot_gcode.SnapshotIndex, 6) self.assertEqual(snapshot_gcode.end_index(), 14) # verify the return coordinates self.assertEqual(snapshot_gcode.ReturnX, 100) self.assertEqual(snapshot_gcode.ReturnY, 50) self.assertEqual(snapshot_gcode.ReturnZ, 0) # Get the next coordinate in the path snapshot_gcode = snapshot_gcode_generator.create_snapshot_gcode( 101, 51, 0, 3600, True, False, self.Extruder, 0.5, "SavedCommand") # verify the created gcode self.assertEqual(snapshot_gcode.GcodeCommands[0], "G1 F6000") self.assertEqual(snapshot_gcode.GcodeCommands[1], "G1 Z0.500") self.assertEqual(snapshot_gcode.GcodeCommands[2], "G90") self.assertEqual(snapshot_gcode.GcodeCommands[3], "G1 F6000") self.assertEqual(snapshot_gcode.GcodeCommands[4], "G1 X100.000 Y100.000") self.assertEqual(snapshot_gcode.GcodeCommands[5], "M400") self.assertEqual(snapshot_gcode.GcodeCommands[6], "M114") self.assertEqual(snapshot_gcode.GcodeCommands[7], "G1 X101.000 Y51.000") self.assertEqual(snapshot_gcode.GcodeCommands[8], "G91") self.assertEqual(snapshot_gcode.GcodeCommands[9], "G1 F6000") self.assertEqual(snapshot_gcode.GcodeCommands[10], "G1 Z-0.500") self.assertEqual(snapshot_gcode.GcodeCommands[11], "G1 F3600") self.assertEqual(snapshot_gcode.GcodeCommands[12], "SAVEDCOMMAND") self.assertEqual(snapshot_gcode.GcodeCommands[13], "M400") self.assertEqual(snapshot_gcode.GcodeCommands[14], "M114") # verify the indexes of the generated gcode self.assertEqual(snapshot_gcode.SnapshotIndex, 6) self.assertEqual(snapshot_gcode.end_index(), 14) # verify the return coordinates self.assertEqual(snapshot_gcode.ReturnX, 101) self.assertEqual(snapshot_gcode.ReturnY, 51) self.assertEqual(snapshot_gcode.ReturnZ, 0) def test_GetSnapshotGcode_Relative_RelativeCoordinates_AbsoluteExtruder_ZhopTooHigh(self): """Test snapshot gcode with relative stabilization, relative coordinates, absolute extruder, z is too high to hop, no retraction """ # test with relative coordinates, absolute extruder coordinates, z hop impossible (current z height will not # allow this since it puts things outside of the bounds) use relative coordinates for stabilizations self.Settings.current_stabilization().x_type = "relative" self.Settings.current_stabilization().x_relative = 50 # 125 self.Settings.current_stabilization().y_type = "relative" self.Settings.current_stabilization().y_relative = 100 # 200 self.Settings.current_snapshot().retract_before_move = False snapshot_gcode_generator = SnapshotGcodeGenerator( self.Settings, self.create_octoprint_printer_profile()) # create snapshot_gcode = snapshot_gcode_generator.create_snapshot_gcode( 10, 10, 200, 3600, True, False, self.Extruder, 0.5, "SavedCommand") # verify the created gcode self.assertEqual(snapshot_gcode.GcodeCommands[0], "G90") self.assertEqual(snapshot_gcode.GcodeCommands[1], "G1 F6000") self.assertEqual(snapshot_gcode.GcodeCommands[2], "G1 X125.000 Y200.000") self.assertEqual(snapshot_gcode.GcodeCommands[3], "M400") self.assertEqual(snapshot_gcode.GcodeCommands[4], "M114") self.assertEqual(snapshot_gcode.GcodeCommands[5], "G1 X10.000 Y10.000") self.assertEqual(snapshot_gcode.GcodeCommands[6], "G91") self.assertEqual(snapshot_gcode.GcodeCommands[7], "G1 F3600") self.assertEqual(snapshot_gcode.GcodeCommands[8], "SAVEDCOMMAND") self.assertEqual(snapshot_gcode.GcodeCommands[9], "M400") self.assertEqual(snapshot_gcode.GcodeCommands[10], "M114") # verify the indexes of the generated gcode self.assertTrue(snapshot_gcode.SnapshotIndex == 4) self.assertTrue(snapshot_gcode.end_index() == 10) # verify the return coordinates self.assertTrue(snapshot_gcode.ReturnX == 10) self.assertTrue(snapshot_gcode.ReturnY == 10) self.assertTrue(snapshot_gcode.ReturnZ == 200) def test_GetSnapshotGcode_SnapshotCommands(self): # test with relative paths, absolute extruder coordinates, retract and z hop # use relative coordinates for stabilizations self.Settings.current_stabilization().x_type = "fixed_path" self.Settings.current_stabilization().x_fixed_path = "50,100" # 125,250 self.Settings.current_stabilization().x_fixed_path_loop = False self.Settings.current_stabilization().x_fixed_path_invert_loop = False self.Settings.current_stabilization().y_type = "fixed_path" self.Settings.current_stabilization().y_fixed_path = "50,100" # 100,200 self.Settings.current_stabilization().y_fixed_path_loop = False self.Settings.current_stabilization().y_fixed_path_invert_loop = False self.Settings.current_snapshot().retract_before_move = True snapshot_gcode_generator = SnapshotGcodeGenerator( self.Settings, self.create_octoprint_printer_profile()) self.Extruder.is_retracted = lambda: True snapshot_gcode = snapshot_gcode_generator.create_snapshot_gcode( 100, 50, 0, 3600, True, False, self.Extruder, 0.5, "SavedCommand") # verify the snapshot commands self.assertEqual(snapshot_gcode.get_snapshot_commands()[0], "G1 F6000") self.assertEqual(snapshot_gcode.get_snapshot_commands()[1], "G1 Z0.500") self.assertEqual(snapshot_gcode.get_snapshot_commands()[2], "G90") self.assertEqual(snapshot_gcode.get_snapshot_commands()[3], "G1 F6000") self.assertEqual(snapshot_gcode.get_snapshot_commands()[4], "G1 X50.000 Y50.000") self.assertEqual(snapshot_gcode.get_snapshot_commands()[5], "M400") self.assertEqual(snapshot_gcode.get_snapshot_commands()[6], "M114") def test_GetSnapshotGcode_ReturnCommands(self): # test with relative paths, absolute extruder coordinates, retract and z hop # use relative coordinates for stabilizations self.Settings.current_stabilization().x_type = "fixed_path" self.Settings.current_stabilization().x_fixed_path = "50,100" # 125,250 self.Settings.current_stabilization().x_fixed_path_loop = False self.Settings.current_stabilization().x_fixed_path_invert_loop = False self.Settings.current_stabilization().y_type = "fixed_path" self.Settings.current_stabilization().y_fixed_path = "50,100" # 100,200 self.Settings.current_stabilization().y_fixed_path_loop = False self.Settings.current_stabilization().y_fixed_path_invert_loop = False self.Settings.current_snapshot().retract_before_move = True snapshot_gcode_generator = SnapshotGcodeGenerator( self.Settings, self.create_octoprint_printer_profile()) self.Extruder.is_retracted = lambda: True snapshot_gcode = snapshot_gcode_generator.create_snapshot_gcode( 100, 50, 0, 3600, True, False, self.Extruder, 0.5, "SavedCommand") # verify the return commands self.assertEqual(snapshot_gcode.get_return_commands()[0], "G1 X100.000 Y50.000") self.assertEqual(snapshot_gcode.get_return_commands()[1], "G91") self.assertEqual(snapshot_gcode.get_return_commands()[2], "G1 F6000") self.assertEqual(snapshot_gcode.get_return_commands()[3], "G1 Z-0.500") self.assertEqual(snapshot_gcode.get_return_commands()[4], "G1 F3600") self.assertEqual(snapshot_gcode.get_return_commands()[5], "SAVEDCOMMAND") self.assertEqual(snapshot_gcode.get_return_commands()[6], "M400") self.assertEqual(snapshot_gcode.get_return_commands()[7], "M114")
class TestTrigger(unittest.TestCase): def setUp(self): self.Settings = OctolapseSettings(NamedTemporaryFile().name) self.PrinterTolerance = 0.0 def tearDown(self): del self.Settings def test_IsInPosition_Rect_Forbidden(self): restrictions_dict = [{ "Shape": "rect", "X": 10.0, "Y": 10.0, "X2": 20.0, "Y2": 20.0, "Type": "forbidden", "R": 1.0 }] restrictions = self.Settings.current_snapshot( ).get_trigger_position_restrictions(restrictions_dict) self.assertTrue( trigger.is_in_position(restrictions, 0, 0, self.PrinterTolerance)) self.assertTrue( trigger.is_in_position(restrictions, 100, 0, self.PrinterTolerance)) self.assertTrue( trigger.is_in_position(restrictions, 20.1, 20.1, self.PrinterTolerance)) self.assertTrue( trigger.is_in_position(restrictions, 15, 25, self.PrinterTolerance)) self.assertTrue( trigger.is_in_position(restrictions, 25, 15, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 10, 10, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 15, 15, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 20, 20, self.PrinterTolerance)) def test_IsInPosition_Rect_Required(self): restrictions_dict = [{ "Shape": "rect", "X": 10.0, "Y": 10.0, "X2": 20.0, "Y2": 20.0, "Type": "required", "R": 1.0 }] restrictions = self.Settings.current_snapshot( ).get_trigger_position_restrictions(restrictions_dict) self.assertFalse( trigger.is_in_position(restrictions, 0, 0, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 100, 0, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 20.1, 20.1, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 15, 25, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 25, 15, self.PrinterTolerance)) self.assertTrue( trigger.is_in_position(restrictions, 10, 10, self.PrinterTolerance)) self.assertTrue( trigger.is_in_position(restrictions, 15, 15, self.PrinterTolerance)) self.assertTrue( trigger.is_in_position(restrictions, 20, 20, self.PrinterTolerance)) def test_IsInPosition_Rect_ForbiddenAndRequired(self): # test to restrictions, forbidden and required, have them overlap. restrictions_dict = [ { "Shape": "rect", "X": 10.0, "Y": 10.0, "X2": 20.0, "Y2": 20.0, "Type": "required", "R": 1.0 }, { "Shape": "rect", "X": 15.0, "Y": 15.0, "X2": 25.0, "Y2": 25.0, "Type": "forbidden", "R": 1.0 }, ] restrictions = self.Settings.current_snapshot( ).get_trigger_position_restrictions(restrictions_dict) # out of all areas, restricted and forbidden self.assertFalse( trigger.is_in_position(restrictions, 0, 0, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 100, 0, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 12.5, 25, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 25, 12.5, self.PrinterTolerance)) # test only in forbidden area self.assertFalse( trigger.is_in_position(restrictions, 20.1, 25, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 20.1, 20.1, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 25, 20.1, self.PrinterTolerance)) # test in required area only self.assertTrue( trigger.is_in_position(restrictions, 10, 10, self.PrinterTolerance)) self.assertTrue( trigger.is_in_position(restrictions, 12.5, 12.5, self.PrinterTolerance)) self.assertTrue( trigger.is_in_position(restrictions, 14.99, 14.99, self.PrinterTolerance)) # test overlapping area self.assertFalse( trigger.is_in_position(restrictions, 15, 15, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 20, 20, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 15, 20, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 20, 15, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 17.5, 17.5, self.PrinterTolerance)) def test_IsInPosition_Circle_Forbidden(self): restrictions_dict = [{ "Shape": "circle", "R": 1.0, "Y": 10.0, "X": 10.0, "Type": "forbidden", "X2": 0, "Y2": 0 }] restrictions = self.Settings.current_snapshot( ).get_trigger_position_restrictions(restrictions_dict) # tests outside forbidden area self.assertTrue( trigger.is_in_position(restrictions, 0, 0, self.PrinterTolerance)) self.assertTrue( trigger.is_in_position(restrictions, 100, 0, self.PrinterTolerance)) self.assertTrue( trigger.is_in_position(restrictions, 9, 9, self.PrinterTolerance)) self.assertTrue( trigger.is_in_position(restrictions, 11, 11, self.PrinterTolerance)) self.assertTrue( trigger.is_in_position(restrictions, 9, 11, self.PrinterTolerance)) self.assertTrue( trigger.is_in_position(restrictions, 11, 9, self.PrinterTolerance)) # tests inside forbidden area self.assertFalse( trigger.is_in_position(restrictions, 10, 10, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 10, 9, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 9, 10, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 10, 11, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 11, 10, self.PrinterTolerance)) def test_IsInPosition_Circle_Required(self): restrictions_dict = [{ "Shape": "circle", "R": 1.0, "Y": 10.0, "X": 10.0, "Type": "required", "X2": 20.0, "Y2": 20.0 }] restrictions = self.Settings.current_snapshot( ).get_trigger_position_restrictions(restrictions_dict) # tests outside area self.assertFalse( trigger.is_in_position(restrictions, 0, 0, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 100, 0, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 9, 9, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 11, 11, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 9, 11, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 11, 9, self.PrinterTolerance)) # tests inside area self.assertTrue( trigger.is_in_position(restrictions, 10, 10, self.PrinterTolerance)) self.assertTrue( trigger.is_in_position(restrictions, 10, 9, self.PrinterTolerance)) self.assertTrue( trigger.is_in_position(restrictions, 9, 10, self.PrinterTolerance)) self.assertTrue( trigger.is_in_position(restrictions, 10, 11, self.PrinterTolerance)) self.assertTrue( trigger.is_in_position(restrictions, 11, 10, self.PrinterTolerance)) def test_IsInPosition_Circle_ForbiddenAndRequired(self): # test to restrictions, forbidden and required, have them overlap. restrictions_dict = [ { "Shape": "circle", "R": 1.0, "Y": 10.0, "X": 10.0, "Type": "required", "X2": 20.0, "Y2": 20.0 }, { "Shape": "circle", "R": 1.0, "Y": 10.0, "X": 11.0, "Type": "forbidden", "X2": 25.0, "Y2": 25.0 }, ] restrictions = self.Settings.current_snapshot( ).get_trigger_position_restrictions(restrictions_dict) # out of all areas, restricted and forbidden self.assertFalse( trigger.is_in_position(restrictions, 0, 0, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 100, 0, self.PrinterTolerance)) # test only in forbidden area self.assertFalse( trigger.is_in_position(restrictions, 12, 10, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 11, 11, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 11, 9, self.PrinterTolerance)) # test in required area only self.assertTrue( trigger.is_in_position(restrictions, 10, 11, self.PrinterTolerance)) self.assertTrue( trigger.is_in_position(restrictions, 10, 9, self.PrinterTolerance)) self.assertTrue( trigger.is_in_position(restrictions, 9, 10, self.PrinterTolerance)) # test overlapping area self.assertFalse( trigger.is_in_position(restrictions, 10, 10, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 11, 10, self.PrinterTolerance)) self.assertFalse( trigger.is_in_position(restrictions, 10.5, 10, self.PrinterTolerance))
class TestLayerTrigger(unittest.TestCase): def setUp(self): self.Settings = OctolapseSettings(NamedTemporaryFile().name) self.Settings.current_printer().e_axis_default_mode = 'relative' self.Settings.current_printer().xyz_axes_default_mode = 'absolute' self.Settings.current_printer().auto_detect_position = False 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_octoprint_printer_profile() def tearDown(self): del self.Settings del self.OctoprintPrinterProfile @staticmethod def create_octoprint_printer_profile(): return dict(volume=dict( width=250, depth=200, height=200, formFactor="Not A Circle", custom_box=False, )) def test_LayerTrigger_LayerChange(self): """Test the layer trigger for layer changes triggers""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) trigger = LayerTrigger(self.Settings) trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, None, None, None, None, None, None) # Ignore extruder trigger.RequireZHop = False # no zhop required trigger.HeightIncrement = 0 # Trigger on any height change # test initial state self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # send commands that normally would trigger a layer change, but without all axis homed. position.update("g0 x0 y0 z.2 e1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # Home all axis and try again position.update("g28") trigger.update(position) position.update("g0 x0 y0 z.2 e1") trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # extrude again on the same layer and make sure it does NOT trigger position.update("g0 x1 y1 z.2 e1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # move to higher layer, but do not extrude (no layer change) position.update("g0 x1 y1 z.4") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) position.update("g0 x2 y2 z.4") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # return to previous layer, do not extrude position.update("g0 x2 y2 z.2") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) position.update("g0 x4 y4 z.2") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # extrude again on current layer position.update("g0 x2 y2 z.2 e1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # move up two times, down and extrude (this should trigger after the final command position.update("g0 x2 y2 z.4") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) position.update("g0 x2 y2 z.6") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) position.update("g0 x2 y2 z.4 e1") trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # This should never happen in a print, but test extruding on previous layers # move down to previous layer, extrude, position.update("g0 x2 y2 z.2 e1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # move back to current layer (.4), extrude (no trigger) position.update("g0 x2 y2 z.4 e1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # move up one more layer and extrude (trigger) position.update("g0 x2 y2 z.6 e1") trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) def test_LayerTrigger_LayerChange_DefaultExtruderTriggers(self): position = Position(self.Settings, self.OctoprintPrinterProfile, False) trigger = LayerTrigger(self.Settings) trigger.ExtruderTriggers = ExtruderTriggers(False, True, True, False, None, None, True, True, None, False) trigger.RequireZHop = False # no zhop required trigger.HeightIncrement = 0 # Trigger on any height change # create some gcode gcode = [] # get the startup gcode gcode.extend(self.GetPrintStartGcode) # start layer 1 gcode.append(('G1 Z0.250 F7200.000', False, "")) # start priming extruder gcode.append( ('G1 X50.0 E80.0 F1000.0', False, "ExtrudingStart")) # forbidden gcode.append(('G1 X160.0 E20.0 F1000.0', True, "Extruding")) gcode.append(('G1 Z0.200 F7200.000', False, "Extruding")) gcode.append(('G1 X220.0 E13 F1000.0', False, "Extruding")) gcode.append(('G1 X240.0 E0 F1000.0', False, "Extruding")) # Object print is starting gcode.append(('G1 E-4.00000 F3000.00000', False, "On Retracting, OnRetractingStart")) gcode.append(('G1 Z0.700 F7200.000', False, "FullyRetracted, Zhop")) gcode.append( ('G1 X117.061 Y98.921 F7200.000', False, "FullyRetracted, Zhop")) gcode.append(('G1 Z0.200 F7200.000', False, "FullyRetracted")) gcode.append( ('G1 E4.00000 F3000.00000', False, "DetractingStart, Detracted")) gcode.append(('M204 S1000', False, "Primed")) gcode.append(('G1 F1800', False, "Primed")) # start extruding gcode.append(('G1 X117.508 Y98.104 E0.02922', False, "ExtrudingStart")) # forbidden gcode.append(('G1 X117.947 Y97.636 E0.02011', False, "Extruding")) gcode.append(('G1 X118.472 Y97.267 E0.02011', False, "Extruding")) gcode.append(('G1 X119.061 Y97.013 E0.02011', False, "Extruding")) gcode.append(('G1 X119.690 Y96.884 E0.02011', False, "Extruding")) gcode.append(('G1 X130.004 Y96.869 E0.32341', False, "Extruding")) gcode.append(('G1 X131.079 Y97.061 E0.03423', False, "Extruding")) # Retraction gcode.append(('G1 E-2.40000 F3000.00000', False, "RetractingStart, Retracting, PartiallyRetracted")) gcode.append(('G1 F5760', False, "Retracting, PartiallyRetracted")) gcode.append(('G1 X119.824 Y97.629 E-0.50464', False, "Retracting, PartiallyRetracted")) gcode.append(('G1 F5760', False, "Retracting, PartiallyRetracted")) gcode.append(('G1 X121.876 Y97.628 E-1.01536', False, "Retracting, PartiallyRetracted")) gcode.append( ('G1 E-0.08000 F3000.00000', False, "Retracting, Fully Retracted")) # Retracted, Zhop gcode.append(('G1 Z0.700 F7200.000', False, "FullyRetracted, Zhop")) # Moved while lifted gcode.append( ('G1 X120.587 Y100.587 F7200.000', False, "FullyRetracted, Zhop")) gcode.append(('G1 Z0.200 F7200.000', False, "FullyRetracted")) # Zhop complete gcode.append( ('G1 E4.00000 F3000.00000', False, "DetractingStart, Detracted")) # Retraction Complete gcode.append(('G1 F1800', False, "Primed")) # primed gcode.append( ('G1 X129.413 Y100.587 E0.27673', False, "ExtrudingStart")) gcode.append(('G1 X129.413 Y109.413 E0.27673', False, "Extruding")) gcode.append(('G1 X120.587 Y109.413 E0.27673', False, "Extruding")) gcode.append(('G1 X120.587 Y100.647 E0.27485', False, "Extruding")) gcode.append(('G1 X120.210 Y100.210 F7200.000', False, "Extruding")) # layer 2 # after layer change # retract gcode.append(('G1 E-4.00000 F3000.00000', False, "RetractingStart")) # zhop gcode.append(('G1 Z0.900 F7200.000', False, "FullyRetracted, Zhop")) # move while lifted gcode.append( ('G1 X133.089 Y99.490 F7200.000', False, "FullyRetracted, Zhop")) # end zhop gcode.append(('G1 Z0.400 F7200.000', False, "FullyRetracted")) # detract gcode.append(('G1 E4.00000 F3000.00000', False, "DetractingStart")) gcode.append(('G1 F3000', False, "Detracted, Primed")) # start etruding gcode.append( ('G1 X133.128 Y110.149 E0.33418', False, "ExtrudingStart")) gcode.append(('G1 X132.942 Y111.071 E0.02950', True, "Extruding")) gcode.append(('G1 X132.492 Y111.896 E0.02950', False, "Extruding")) gcode.append(('G1 X132.020 Y112.393 E0.02148', False, "Extruding")) gcode.append(('G1 X131.447 Y112.777 E0.02161', False, "Extruding")) # layer 3 gcode.append(('G1 Z2.600 F7200.000', False, "Primed")) gcode.append(('G1 X120.632 Y100.632 F7200.000', False, "Primed")) gcode.append(('M204 S800', False, "Primed")) gcode.append(('G1 F1200', False, "Primed")) gcode.append( ('G1 X129.368 Y100.632 E0.29570', False, "ExtrudingStart")) gcode.append(('G1 X129.368 Y109.368 E0.29570', True, "Extruding")) gcode.append(('G1 X120.632 Y109.368 E0.29570', False, "Extruding")) gcode.append(('G1 X120.632 Y100.692 E0.29367', False, "Extruding")) gcode.append(('M204 S1000', False, "Primed")) gcode.append(('G1 X120.225 Y100.225 F7200.000', False, "Extruding")) gcode.append(('M204 S800', False, "Primed")) gcode.append(('G1 F1200', False, "Extruding")) gcode.append(('G1 X129.775 Y100.225 E0.32326', False, "Extruding")) # layer 4 gcode.append(('G1 Z2.800 F7200.000', False, "Primed")) gcode.append(('G1 X120.632 Y109.368 F7200.000', False, "Primed")) gcode.append(('M204 S800', False, "Primed")) gcode.append(('G1 F1200', False, "Primed")) gcode.append( ('G1 X120.632 Y100.632 E0.29570', False, "ExtrudingStart")) gcode.append(('G1 X129.368 Y100.632 E0.29570', True, "Extruding")) gcode.append(('G1 X129.368 Y109.368 E0.29570', False, "Extruding")) gcode.append(('G1 X120.692 Y109.368 E0.29367', False, "Extruding")) gcode.append(('M204 S1000', False, "Primed")) gcode.append(('G1 X120.225 Y109.775 F7200.000', False, "")) gcode.append(('M204 S800', False, "Primed")) gcode.append(('G1 F1200', False, "Primed")) gcode.append( ('G1 X120.225 Y100.225 E0.32326', False, "ExtrudingStart")) gcode.append(('G1 X129.775 Y100.225 E0.32326', False, "Extruding")) gcode.append(('G1 X129.775 Y109.775 E0.32326', False, "Extruding")) gcode.append(('G1 X120.285 Y109.775 E0.32123', False, "Extruding")) # loop through all of the Gcode and test triggering for command in gcode: gcode_command = command[0] should_trigger = command[1] comment = command[2] position.update(gcode_command) trigger.update(position) self.assertTrue( trigger.is_triggered(0) == should_trigger, "Should have triggered on {0} command. Command comment:". format(gcode_command, comment)) @property def GetPrintStartGcode(self): # create gcode list gcode = [('T0', False, "select tool 0"), ('M104 S255', False, "set extruder temp"), ('M140 S100', False, "set bed temp"), ('M190 S100', False, "wait for bed temp"), ('M109 S255', False, "wait for extruder temp"), ('G21', False, "set units to millimeters"), ('G90', False, "use absolute coordinates"), ('M83', False, "use relative distances for extrusion"), ('G28 W', False, ""), ('G80', False, ""), ('G92 E0.0', False, ""), ('M203 E100', False, ""), ('M92 E140', False, ""), ('G92 E0.0', False, ""), ('M900 K200', False, "")] # Print Start Code return gcode def test_LayerTrigger_HeightChange(self): """Test the layer trigger height change """ position = Position(self.Settings, self.OctoprintPrinterProfile, False) trigger = LayerTrigger(self.Settings) trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, None, None, None, None, None, None) # Ignore extruder trigger.RequireZHop = False # no zhop required trigger.HeightIncrement = .25 # Trigger every .25 # test initial state self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # send commands that normally would trigger a layer change, but without all axis homed. position.update("g0 x0 y0 z.2 e1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # cur increment 0.25 position.update("g28") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # extrude at height 0.2, should trigger position.update("g0 x0 y0 z.2 e1") trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # cur increment 0.25 # move to higher layer, but do not extrude (no layer change) position.update("g0 x1 y1 z.4") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) position.update("g0 x2 y2 z.4") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # cur increment 0.25 # return to previous layer, do not extrude position.update("g0 x2 y2 z.2") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) position.update("g0 x4 y4 z.2") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # cur increment 0.25 # extrude again on current layer position.update("g0 x2 y2 z.2 e1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # cur increment 0.25 # move up two times, down and extrude (this should trigger after the final command position.update("g0 x2 y2 z.4") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) position.update("g0 x2 y2 z.6") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) position.update("g0 x2 y2 z.4 e1") trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # cur increment 0.5 # This should never happen in a print, but test extruding on previous layers # move down to previous layer, extrude, position.update("g0 x2 y2 z.2 e1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # move back to current layer (.4), extrude (no trigger) position.update("g0 x2 y2 z.4 e1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # move up one more layer and extrude (trigger) position.update("g0 x2 y2 z.6 e1") trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # test very close to height increment (.74) # move up one more layer and extrude (trigger) position.update("g0 x2 y2 z0.74 e1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # now it should trigger position.update("m114") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # Test at the increment (.75) position.update("g0 x2 y2 z0.7500 e1") trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) def test_LayerTrigger_ExtruderTriggers_NotHomed(self): """Make sure nothing triggers when the axis aren't homed""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) trigger = LayerTrigger(self.Settings) trigger.RequireZHop = False # no zhop required trigger.HeightIncrement = 0 # Trigger on every layer change position.Extruder.PrinterRetractionLength = 4 # Try on extruding start trigger.ExtruderTriggers = ExtruderTriggers(True, None, None, None, None, None, None, None, None, None) position.update("g0 x0 y0 z.2 e1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # try out on extruding trigger.ExtruderTriggers = ExtruderTriggers(None, True, None, None, None, None, None, None, None, None) position.update("g0 x0 y0 z.3 e1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # try out on primed trigger.ExtruderTriggers = ExtruderTriggers(None, None, True, None, None, None, None, None, None, None) position.update("g0 x0 y0 z.4 e1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # try out on retracting start trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, True, None, None, None, None, None, None) position.update("g0 x0 y0 z.5 e-1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # try out on retracting trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, True, None, None, None, None, None) position.update("g0 x0 y0 z.5 e-1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # try out on partially retracted trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, None, True, None, None, None, None) position.update("g0 x0 y0 z.5 e-1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # try out on retracted trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, None, None, True, None, None, None) position.update("g0 x0 y0 z.5 e-1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # try out on detracting trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, None, None, True, None, None, None) position.update("g0 x0 y0 z.5 e1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) def test_LayerTrigger_ExtruderTriggers(self): """Test All Extruder Triggers""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) # home the axis position.update("G28") trigger = LayerTrigger(self.Settings) trigger.RequireZHop = False # no zhop required trigger.HeightIncrement = 0 # Trigger on every layer change # get the current extruder state state = position.Extruder.get_state(0) # Try on extruding start right after home, should fail since we haven't extruded yet trigger.ExtruderTriggers = ExtruderTriggers(True, None, None, None, None, None, None, None, None, None) state.IsExtrudingStart = True trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # Try again, should trigger after the extrusion position.update("G1 E1") trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # Reset the previous extruder state state = ExtruderState() position.Extruder.StateHistory[0] = state state.IsPrimed = False # try out on extruding state.IsExtruding = True trigger.ExtruderTriggers = ExtruderTriggers(None, True, None, None, None, None, None, None, None, None) trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # Reset the previous extruder state state = ExtruderState() position.Extruder.StateHistory[0] = state state.IsPrimed = False # try out on primed trigger.ExtruderTriggers = ExtruderTriggers(None, None, True, None, None, None, None, None, None, None) state.IsPrimed = True trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # Reset the previous extruder state state = ExtruderState() position.Extruder.StateHistory[0] = state state.IsPrimed = False # try out on retracting start trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, True, None, None, None, None, None, None) state.IsRetractingStart = True trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # Reset the previous extruder state state = ExtruderState() position.Extruder.StateHistory[0] = state state.IsPrimed = False # try out on retracting trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, True, None, None, None, None, None) state.IsRetracting = True trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # Reset the previous extruder state state = ExtruderState() position.Extruder.StateHistory[0] = state state.IsPrimed = False # try out on partially retracted trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, None, True, None, None, None, None) state.IsPartiallyRetracted = True trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # Reset the previous extruder state state = ExtruderState() position.Extruder.StateHistory[0] = state state.IsPrimed = False # try out on retracted trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, None, None, True, None, None, None) state.IsRetracted = True trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # Reset the previous extruder state state = ExtruderState() position.Extruder.StateHistory[0] = state state.IsPrimed = False # try out on detracting Start trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, None, None, None, True, None, None) state.IsDetractingStart = True trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # Reset the previous extruder state state = ExtruderState() position.Extruder.StateHistory[0] = state state.IsPrimed = False # try out on detracting Start trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, None, None, None, None, True, None) state.IsDetracting = True trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # Reset the previous extruder state state = ExtruderState() position.Extruder.StateHistory[0] = state state.IsPrimed = False trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, None, None, None, None, None, True) state.IsDetracted = True trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) def test_LayerTrigger_ExtruderTriggerWait(self): """Test wait on extruder""" position = Position(self.Settings, self.OctoprintPrinterProfile, False) trigger = LayerTrigger(self.Settings) trigger.RequireZHop = False # no zhop required trigger.HeightIncrement = 0 # Trigger on every layer change # home the axis position.update("G28") # add the current state pos = position.get_position(0) state = position.Extruder.get_state(0) state.IsPrimed = False # Use on extruding start for this test. trigger.ExtruderTriggers = ExtruderTriggers(True, None, None, None, None, None, None, None, None, None) state.IsExtrudingStart = False pos.IsLayerChange = True trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertTrue(trigger.is_waiting(0)) # update again with no change trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertTrue(trigger.is_waiting(0)) # set the trigger and try again state.IsExtrudingStart = True trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) def test_LayerTrigger_LayerChange_ZHop(self): """Test the layer trigger for layer changes triggers""" self.Settings.current_snapshot().layer_trigger_require_zhop = True self.Settings.current_printer().z_hop = .5 position = Position(self.Settings, self.OctoprintPrinterProfile, False) trigger = LayerTrigger(self.Settings) trigger.ExtruderTriggers = ExtruderTriggers(None, None, None, None, None, None, None, None, None, None) # Ignore extruder trigger.HeightIncrement = 0 # Trigger on any height change # test initial state self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # send commands that normally would trigger a layer change, but without all axis homed. position.update("g0 x0 y0 z.2 e1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # Home all axis and try again, will not trigger or wait, previous axis not homed position.update("g28") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # Waiting on ZHop position.update("g0 x0 y0 z.2 e1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertTrue(trigger.is_waiting(0)) # try zhop position.update("g0 x0 y0 z.7 ") trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # extrude on current layer, no trigger (wait on zhop) position.update("g0 x0 y0 z.7 e1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertTrue(trigger.is_waiting(0)) # do not extrude on current layer, still waiting position.update("g0 x0 y0 z.7 ") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertTrue(trigger.is_waiting(0)) # partial hop, but close enough based on our printer measurement tolerance (0.005) position.update("g0 x0 y0 z1.1999") trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # creat wait state position.update("g0 x0 y0 z1.3 e1") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertTrue(trigger.is_waiting(0)) # move down (should never happen, should behave properly anyway) position.update("g0 x0 y0 z.8") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertTrue(trigger.is_waiting(0)) # move back up to current layer (should NOT trigger zhop) position.update("g0 x0 y0 z1.3") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertTrue(trigger.is_waiting(0)) # move up a bit, not enough to trigger zhop position.update("g0 x0 y0 z1.795") trigger.update(position) self.assertFalse(trigger.is_triggered(0)) self.assertTrue(trigger.is_waiting(0)) # move up a bit, just enough to trigger zhop position.update("g0 x0 y0 z1.7951") trigger.update(position) self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0))
class TestGcodeTrigger(unittest.TestCase): def setUp(self): self.Settings = OctolapseSettings(NamedTemporaryFile().name) self.Settings.current_printer().auto_detect_position = False 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_octoprint_printer_profile() def tearDown(self): del self.Settings del self.OctoprintPrinterProfile @staticmethod def create_octoprint_printer_profile(): return { "volume": { "custom_box": False, "width": 250, "depth": 200, "height": 200 } } def test_GcodeTrigger(self): """Test the gcode triggers""" self.Settings.current_snapshot().gcode_trigger_require_zhop = False position = Position(self.Settings, self.OctoprintPrinterProfile, False) trigger = GcodeTrigger(self.Settings) # test initial state self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # send a command that is NOT the snapshot command using the defaults trigger.update(position, "NotTheSnapshotCommand") self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # send a command that is the snapshot command without the axis being homes trigger.update(position, "snap") self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # reset, set relative extruder and absolute xyz, home the axis, and resend the snap command, should wait # since we require the home command to complete (sent to printer) before triggering position.update("M83") position.update("G90") position.update("G28") trigger.update(position, "snap") self.assertFalse(trigger.is_triggered(0)) self.assertTrue(trigger.is_waiting(0)) # try again, Snap is encountered, but it must be the previous command to trigger position.update("G0 X0 Y0 Z0 E1 F0") trigger.update(position, "G0 X0 Y0 Z0 E1 F0") self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # try again, but this time set RequireZHop to true trigger.RequireZHop = True trigger.update(position, "snap") self.assertFalse(trigger.is_triggered(0)) self.assertTrue(trigger.is_waiting(0)) # send another command to see if we are still waiting trigger.update(position, "NotTheSnapshotCommand") self.assertFalse(trigger.is_triggered(0)) self.assertTrue(trigger.is_waiting(0)) # fake a zhop position.is_zhop = lambda x: True trigger.update(position, "NotTheSnapshotCommand") self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # send a command that is NOT the snapshot command using the defaults trigger.update(position, "NotTheSnapshotCommand") self.assertFalse(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0)) # change the snapshot triggers and make sure they are working self.Settings.current_snapshot().gcode_trigger_require_zhop = None self.Settings.current_snapshot().gcode_trigger_on_extruding = True self.Settings.current_snapshot( ).gcode_trigger_on_extruding_start = None self.Settings.current_snapshot().gcode_trigger_on_primed = None self.Settings.current_snapshot().gcode_trigger_on_retracting = None self.Settings.current_snapshot( ).gcode_trigger_on_partially_retracted = None self.Settings.current_snapshot().gcode_trigger_on_retracted = None self.Settings.current_snapshot( ).gcode_trigger_on_detracting_start = None self.Settings.current_snapshot().gcode_trigger_on_detracting = None self.Settings.current_snapshot().gcode_trigger_on_detracted = None trigger = GcodeTrigger(self.Settings) # send a command that is the snapshot command using the defaults trigger.update(position, "snap") self.assertFalse(trigger.is_triggered(0)) self.assertTrue(trigger.is_waiting(0)) # change the extruder state and test # should not trigger because trigger tests the previous command position.update("G0 X0 Y0 Z0 E10 F0") trigger.update(position, "NotTheSnapshotCommand") self.assertTrue(trigger.is_triggered(0)) self.assertFalse(trigger.is_waiting(0))
def setUp(self): self.Settings = OctolapseSettings(NamedTemporaryFile().name) self.Extruder = Extruder(self.Settings) # set the retraction distance self.Extruder.Printerretraction_length = 4
def setUp(self): self.Settings = OctolapseSettings(NamedTemporaryFile().name)
class Test_GcodeTrigger(unittest.TestCase): def setUp(self): self.Settings = OctolapseSettings("c:\\test\\") self.OctoprintPrinterProfile = self.CreateOctoprintPrinterProfile() def tearDown(self): del self.Settings del self.OctoprintPrinterProfile def CreateOctoprintPrinterProfile(self): return { "volume": { "custom_box": False, "width": 250, "depth": 200, "height": 200 } } def test_GcodeTrigger(self): """Test the gcode triggers""" self.Settings.CurrentSnapshot().gcode_trigger_require_zhop = False position = Position(self.Settings, self.OctoprintPrinterProfile, False) trigger = GcodeTrigger(self.Settings) # test initial state self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == False) # send a command that is NOT the snapshot command using the defaults trigger.Update(position, "NotTheSnapshotCommand") self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == False) # send a command that is the snapshot command without the axis being homes trigger.Update(position, "snap") self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == False) # home the axis and resend the snap command - will be false because the PREVEIOUS state must be homed position.Update("g28") trigger.Update(position, "snap") self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == False) # try again, should now work position.Update("Snap") trigger.Update(position, "snap") self.assertTrue(trigger.IsTriggered == True) self.assertTrue(trigger.IsWaiting == False) # try again, but this time set RequresZHop to true trigger.RequireZHop = True trigger.Update(position, "snap") self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == True) # send another command to see if we are still waiting trigger.Update(position, "NotTheSnapshotCommand") self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == True) # fake a zhop position.IsZHop = True trigger.Update(position, "NotTheSnapshotCommand") self.assertTrue(trigger.IsTriggered == True) self.assertTrue(trigger.IsWaiting == False) # send a command that is NOT the snapshot command using the defaults trigger.Update(position, "NotTheSnapshotCommand") self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == False) # change the snapshot triggers and make sure they are working self.Settings.CurrentSnapshot().gcode_trigger_require_zhop = False self.Settings.CurrentSnapshot().gcode_trigger_on_extruding = True self.Settings.CurrentSnapshot( ).gcode_trigger_on_extruding_start = False self.Settings.CurrentSnapshot().gcode_trigger_on_primed = False self.Settings.CurrentSnapshot().gcode_trigger_on_retracting = False self.Settings.CurrentSnapshot().gcode_trigger_on_retracted = False self.Settings.CurrentSnapshot().gcode_trigger_on_detracting = False trigger = GcodeTrigger(self.Settings) position.Extruder.IsExtruding = False position.Extruder.IsExtrudingStart = False position.Extruder.IsPrimed = False position.Extruder.IsRetracting = False position.Extruder.IsRetracted = False position.Extruder.IsDetracting = False # send a command that is the snapshot command using the defaults trigger.Update(position, "snap") self.assertTrue(trigger.IsTriggered == False) self.assertTrue(trigger.IsWaiting == True) # change the extruder state and test position.Extruder.IsExtruding = True trigger.Update(position, "NotTheSnapshotCommand") self.assertTrue(trigger.IsTriggered == True) self.assertTrue(trigger.IsWaiting == False)