def test_print_gcode_should_create_serial_commander_if_specified_in_config(self,
            mock_SerialCommander,
            mock_SubLayerGenerator, 
            mock_AudioDripZAxis,
            mock_AudioModulationLaserControl,
            mock_GCodeReader,
            mock_AudioWriter,
            mock_Transformer,
            mock_PathToAudio,
            mock_Controller,
            ):
        gcode_path = "FakeFile"
        actual_samples_per_second = 7
        fake_layers = "Fake Layers"
        mock_serialcommander = mock_SerialCommander.return_value
        mock_dripbasedzaxis = mock_AudioDripZAxis.return_value
        mock_audiomodulationlasercontrol = mock_AudioModulationLaserControl.return_value
        mock_gcodereader = mock_GCodeReader.return_value
        mock_sublayergenerator = mock_SubLayerGenerator.return_value
        mock_audiowriter = mock_AudioWriter.return_value
        mock_transformer = mock_Transformer.return_value
        mock_pathtoaudio = mock_PathToAudio.return_value
        mock_controller = mock_Controller.return_value

        mock_audiomodulationlasercontrol.actual_samples_per_second = actual_samples_per_second
        mock_gcodereader.get_layers.return_value = fake_layers

        config = self.default_config
        config.serial.on = True
        config.serial.port = "COM6"
        config.serial.on_command = "ON"
        config.serial.off_command = "OFF"
        api = PrintAPI(config)
        api.print_gcode(gcode_path)

        mock_SerialCommander.assert_called_with("COM6")
        mock_AudioDripZAxis.assert_called_with(
            config.dripper.drips_per_mm,
            config.audio.input.sample_rate,
            config.audio.input.bit_depth,
            mock_serialcommander,
            config.serial.on_command,
            config.serial.off_command
            )
        mock_Controller.assert_called_with(
            mock_audiomodulationlasercontrol,
            mock_pathtoaudio,
            mock_audiowriter,
            mock_sublayergenerator,
            zaxis = mock_dripbasedzaxis,
            status_call_back = None,
            max_lead_distance = config.dripper.max_lead_distance_mm,
            abort_on_error = True
        )
    def test_print_gcode_should_create_serial_commander_if_specified_in_config(
        self,
        mock_SerialCommander,
        mock_SubLayerGenerator,
        mock_AudioDripZAxis,
        mock_AudioModulationLaserControl,
        mock_GCodeReader,
        mock_AudioWriter,
        mock_Transformer,
        mock_PathToAudio,
        mock_Controller,
    ):
        gcode_path = "FakeFile"
        actual_samples_per_second = 7
        fake_layers = "Fake Layers"
        mock_serialcommander = mock_SerialCommander.return_value
        mock_dripbasedzaxis = mock_AudioDripZAxis.return_value
        mock_audiomodulationlasercontrol = mock_AudioModulationLaserControl.return_value
        mock_gcodereader = mock_GCodeReader.return_value
        mock_sublayergenerator = mock_SubLayerGenerator.return_value
        mock_audiowriter = mock_AudioWriter.return_value
        mock_transformer = mock_Transformer.return_value
        mock_pathtoaudio = mock_PathToAudio.return_value
        mock_controller = mock_Controller.return_value

        mock_audiomodulationlasercontrol.actual_samples_per_second = actual_samples_per_second
        mock_gcodereader.get_layers.return_value = fake_layers

        config = self.default_config
        config.serial.on = True
        config.serial.port = "COM6"
        config.serial.on_command = "ON"
        config.serial.off_command = "OFF"
        api = PrintAPI(config)
        api.print_gcode(gcode_path)

        mock_SerialCommander.assert_called_with("COM6")
        mock_AudioDripZAxis.assert_called_with(config.dripper.drips_per_mm,
                                               config.audio.input.sample_rate,
                                               config.audio.input.bit_depth,
                                               mock_serialcommander,
                                               config.serial.on_command,
                                               config.serial.off_command)
        mock_Controller.assert_called_with(
            mock_audiomodulationlasercontrol,
            mock_pathtoaudio,
            mock_audiowriter,
            mock_sublayergenerator,
            zaxis=mock_dripbasedzaxis,
            status_call_back=None,
            max_lead_distance=config.dripper.max_lead_distance_mm,
            abort_on_error=True)
    def test_get_and_set_drips_per_second(
        self,
        mock_SubLayerGenerator,
        mock_TimedDripZAxis,
        mock_AudioModulationLaserControl,
        mock_GCodeReader,
        mock_AudioWriter,
        mock_Transformer,
        mock_PathToAudio,
        mock_Controller,
    ):
        gcode_path = "FakeFile"
        expected_drips_per_second = 12
        mock_timeddripzaxis = mock_TimedDripZAxis.return_value
        mock_timeddripzaxis.get_drips_per_second.return_value = expected_drips_per_second

        config = self.default_config
        config.dripper.dripper_type = 'emulated'
        api = PrintAPI(config)
        api.print_gcode(gcode_path)

        mock_TimedDripZAxis.assert_called_with(
            config.dripper.drips_per_mm,
            drips_per_second=config.dripper.emulated_drips_per_second)
        self.assertTrue(api.can_set_drips_per_second())
        api.set_drips_per_second(expected_drips_per_second)
        self.assertEquals(expected_drips_per_second,
                          api.get_drips_per_second())

        mock_timeddripzaxis.set_drips_per_second.assert_called_with(
            expected_drips_per_second)
예제 #4
0
    def initialize(self):
        self.grid()

        self._elapsed_time = StringVar()
        self._current_layer = IntVar()
        self._current_height = StringVar()
        self._current_model_height = StringVar()
        self._errors = IntVar()
        self._status = StringVar()
        self._stop_button_text = StringVar()
        self._stop_button_text.set("Abort Verification")
        self._current_status = {}

        self._print_api = PrintAPI(self.kwargs['config'],
                                   status_call_back=self.status_call_back)
        if 'filename' in self.kwargs:
            file_to_print = self.kwargs['filename']
            self._print_api.verify_gcode(file_to_print)
        else:
            self._print_api.verify_gcode(self.kwargs['layer_generator'])

        Label(self, text="Verifying Model").grid(column=0, row=5)
        Label(self).grid(column=0, row=8)

        Label(self, text="Elapsed Time").grid(column=0, row=10)
        Label(self, textvariable=self._elapsed_time).grid(column=1, row=10)

        Label(self, text="Layer").grid(column=0, row=20)
        Label(self, textvariable=self._current_layer).grid(column=1, row=20)

        Label(self, text="Model Height (mm)").grid(column=0, row=35)
        Label(self, textvariable=self._current_model_height).grid(column=1,
                                                                  row=35)

        Label(self, text="Status").grid(column=0, row=60)
        Label(self, textvariable=self._status).grid(column=1, row=60)

        Label(self, text="Errors").grid(column=0, row=70)
        Label(self, textvariable=self._errors).grid(column=1, row=70)

        Label(self).grid(column=0, row=70)

        Button(self,
               textvariable=self._stop_button_text,
               command=self._stop_button_click).grid(column=2, row=80)
        Button(self, text="Show Errors",
               command=self._show_errors).grid(column=3, row=80)

        self.update()
    def test_print_gcode_should_create_serial_control_if_specified_in_config(self,
            mock_SerialZAxisControl,
            mock_SubLayerGenerator, 
            mock_DripBasedZAxis,
            mock_AudioModulationLaserControl,
            mock_GCodeReader,
            mock_AudioWriter,
            mock_Transformer,
            mock_PathToAudio,
            mock_Controller,
            ):
        gcode_path = "FakeFile"
        actual_samples_per_second = 7
        fake_layers = "Fake Layers"
        mock_dripbasedzaxis = mock_DripBasedZAxis.return_value
        mock_audiomodulationlasercontrol = mock_AudioModulationLaserControl.return_value
        mock_gcodereader = mock_GCodeReader.return_value
        mock_sublayergenerator = mock_SubLayerGenerator.return_value
        mock_audiowriter = mock_AudioWriter.return_value
        mock_transformer = mock_Transformer.return_value
        mock_pathtoaudio = mock_PathToAudio.return_value
        mock_controller = mock_Controller.return_value
        mock_serialzaxiscontrol = mock_SerialZAxisControl.return_value

        mock_audiomodulationlasercontrol.actual_samples_per_second = actual_samples_per_second
        mock_gcodereader.get_layers.return_value = fake_layers

        config = self.DEFAULT_CONFIG.copy()
        config['use_serial_zaxis'] = True
        config['serial_port'] = "COM6"
        config['serial_on'] = "ON"
        config['serial_off'] = "OFF"
        api = PrintAPI(config)
        api.print_gcode(gcode_path)

        mock_SerialZAxisControl.assert_called_with("COM6", on_command = "ON", off_command = "OFF")
        mock_Controller.assert_called_with(
            mock_audiomodulationlasercontrol,
            mock_pathtoaudio,
            mock_audiowriter,
            mock_sublayergenerator,
            zaxis = mock_dripbasedzaxis,
            zaxis_control = mock_serialzaxiscontrol,
            status_call_back = None,
            max_lead_distance = config['max_lead_distance_mm'],
            abort_on_error = True
        )
    def test_get_and_set_drips_per_second(self,
            mock_SubLayerGenerator, 
            mock_TimedDripZAxis,
            mock_AudioModulationLaserControl,
            mock_GCodeReader,
            mock_AudioWriter,
            mock_Transformer,
            mock_PathToAudio,
            mock_Controller,
            ):
        gcode_path = "FakeFile"
        expected_drips_per_second = 12
        mock_timeddripzaxis = mock_TimedDripZAxis.return_value
        mock_timeddripzaxis.get_drips_per_second.return_value = expected_drips_per_second
        
        config = self.default_config
        config.dripper.dripper_type = 'emulated'
        api = PrintAPI(config)
        api.print_gcode(gcode_path)


        mock_TimedDripZAxis.assert_called_with(config.dripper.drips_per_mm, drips_per_second = config.dripper.emulated_drips_per_second)
        self.assertTrue(api.can_set_drips_per_second())
        api.set_drips_per_second(expected_drips_per_second)
        self.assertEquals(expected_drips_per_second, api.get_drips_per_second())

        mock_timeddripzaxis.set_drips_per_second.assert_called_with(expected_drips_per_second)
    def test_get_status_calls_controller_status(self, 
            mock_AudioDripZAxis,
            mock_AudioModulationLaserControl,
            mock_GCodeReader,
            mock_AudioWriter,
            mock_Transformer,
            mock_PathToAudio,
            mock_Controller,):
        mock_audiomodulationlasercontrol = mock_AudioModulationLaserControl.return_value
        mock_audiomodulationlasercontrol.actual_samples_per_second = 7
        mock_controller = mock_Controller.return_value


        api = PrintAPI(self.default_config)
        api.print_gcode("Spam")
        api.get_status()

        mock_controller.get_status.assert_called_with()
    def test_print_gcode_should_use_specified_dripper_if_specified_in_config(
        self,
        mock_SubLayerGenerator,
        mock_TimedDripZAxis,
        mock_AudioModulationLaserControl,
        mock_GCodeReader,
        mock_AudioWriter,
        mock_Transformer,
        mock_PathToAudio,
        mock_Controller,
    ):
        gcode_path = "FakeFile"
        actual_samples_per_second = 7
        fake_layers = "Fake Layers"
        mock_timeddripzaxis = mock_TimedDripZAxis.return_value
        mock_audiomodulationlasercontrol = mock_AudioModulationLaserControl.return_value
        mock_gcodereader = mock_GCodeReader.return_value
        mock_sublayergenerator = mock_SubLayerGenerator.return_value
        mock_audiowriter = mock_AudioWriter.return_value
        mock_transformer = mock_Transformer.return_value
        mock_pathtoaudio = mock_PathToAudio.return_value
        mock_controller = mock_Controller.return_value

        mock_audiomodulationlasercontrol.actual_samples_per_second = actual_samples_per_second
        mock_gcodereader.get_layers.return_value = fake_layers

        config = self.default_config
        config.dripper.dripper_type = 'emulated'
        api = PrintAPI(config)
        api.print_gcode(gcode_path)

        mock_TimedDripZAxis.assert_called_with(
            config.dripper.drips_per_mm,
            drips_per_second=config.dripper.emulated_drips_per_second)
        mock_Controller.assert_called_with(
            mock_audiomodulationlasercontrol,
            mock_pathtoaudio,
            mock_audiowriter,
            mock_sublayergenerator,
            zaxis=mock_timeddripzaxis,
            status_call_back=None,
            max_lead_distance=config.dripper.max_lead_distance_mm,
            abort_on_error=True)
    def test_print_gcode_should_use_specified_dripper_if_specified_in_config(self,
            mock_SubLayerGenerator, 
            mock_TimedDripZAxis,
            mock_AudioModulationLaserControl,
            mock_GCodeReader,
            mock_AudioWriter,
            mock_Transformer,
            mock_PathToAudio,
            mock_Controller,
            ):
        gcode_path = "FakeFile"
        actual_samples_per_second = 7
        fake_layers = "Fake Layers"
        mock_timeddripzaxis = mock_TimedDripZAxis.return_value
        mock_audiomodulationlasercontrol = mock_AudioModulationLaserControl.return_value
        mock_gcodereader = mock_GCodeReader.return_value
        mock_sublayergenerator = mock_SubLayerGenerator.return_value
        mock_audiowriter = mock_AudioWriter.return_value
        mock_transformer = mock_Transformer.return_value
        mock_pathtoaudio = mock_PathToAudio.return_value
        mock_controller = mock_Controller.return_value

        mock_audiomodulationlasercontrol.actual_samples_per_second = actual_samples_per_second
        mock_gcodereader.get_layers.return_value = fake_layers

        config = self.default_config
        config.dripper.dripper_type = 'emulated'
        api = PrintAPI(config)
        api.print_gcode(gcode_path)

        mock_TimedDripZAxis.assert_called_with(config.dripper.drips_per_mm, drips_per_second = config.dripper.emulated_drips_per_second )
        mock_Controller.assert_called_with(
            mock_audiomodulationlasercontrol,
            mock_pathtoaudio,
            mock_audiowriter,
            mock_sublayergenerator,
            zaxis = mock_timeddripzaxis,
            status_call_back = None,
            max_lead_distance = config.dripper.max_lead_distance_mm,
            abort_on_error = True
        )
    def test_set_drips_per_second_throws_error_if_not_using_emulated_drips(self,
            mock_SubLayerGenerator, 
            mock_AudioDripZAxis,
            mock_AudioModulationLaserControl,
            mock_GCodeReader,
            mock_AudioWriter,
            mock_Transformer,
            mock_PathToAudio,
            mock_Controller,
            ):
        gcode_path = "FakeFile"

        mock_audiodripzaxis = mock_AudioDripZAxis.return_value
        mock_audiodripzaxis.set_drips_per_second.side_effect = Exception()

        config = self.default_config

        api = PrintAPI(config)
        api.print_gcode(gcode_path)

        with self.assertRaises(Exception):
            api.set_drips_per_second(12)
예제 #11
0
    def initialize(self):
        self.grid()
        
        self._elapsed_time = StringVar()
        self._current_layer = IntVar()
        self._current_height = StringVar()
        self._current_model_height = StringVar()
        self._current_drips = IntVar()
        self._waiting_for_drips = StringVar()
        self._skipped_layers = IntVar()
        self._status = StringVar()
        self._stop_button_text = StringVar()
        self._stop_button_text.set("Abort Print")

        self._print_api = PrintAPI(self.kwargs['config'],status_call_back = self.status_call_back)
        if 'filename' in self.kwargs:
            file_to_print = self.kwargs['filename']
            self._print_api.print_gcode(file_to_print)
        else:
            self._print_api.print_layers(self.kwargs['layer_generator'])


        Label(self, text = "Elapsed Time" ).grid(column=0,row=10)
        Label(self, textvariable = self._elapsed_time ).grid(column=1,row=10)

        Label(self, text = "Layer" ).grid(column=0,row=20)
        Label(self, textvariable = self._current_layer ).grid(column=1,row=20)

        Label(self, text = "Actual Height (mm)" ).grid(column=0,row=30)
        Label(self, textvariable = self._current_height ).grid(column=1,row=30)

        Label(self, text = "Model Height (mm)" ).grid(column=0,row=35)
        Label(self, textvariable = self._current_model_height ).grid(column=1,row=35)

        Label(self, text = "Drips" ).grid(column=0,row=40)
        Label(self, textvariable = self._current_drips ).grid(column=1,row=40)

        Label(self, text = "Waiting for drips" ).grid(column=0,row=50)
        Label(self, textvariable = self._waiting_for_drips ).grid(column=1,row=50)

        Label(self, text = "Skipped Layers" ).grid(column=0,row=55)
        Label(self, textvariable = self._skipped_layers ).grid(column=1,row=55)

        Label(self, text = "Status").grid(column=0,row=60)
        Label(self, textvariable = self._status).grid(column=1,row=60)

        Label(self).grid(column=0,row=70)
        
        Button(self,textvariable=self._stop_button_text, command=self._stop_button_click).grid(column=2,row=80)
        
        self.update()
    def test_print_gcode_should_not_print_sublayers_if_option_flase(self,
            mock_SubLayerGenerator, 
            mock_DripBasedZAxis,
            mock_AudioModulationLaserControl,
            mock_GCodeReader,
            mock_AudioWriter,
            mock_Transformer,
            mock_PathToAudio,
            mock_Controller,
            ):
        gcode_path = "FakeFile"
        actual_samples_per_second = 7
        fake_layers = "Fake Layers"
        mock_dripbasedzaxis = mock_DripBasedZAxis.return_value
        mock_audiomodulationlasercontrol = mock_AudioModulationLaserControl.return_value
        mock_gcodereader = mock_GCodeReader.return_value
        mock_sublayergenerator = mock_SubLayerGenerator.return_value
        mock_audiowriter = mock_AudioWriter.return_value
        mock_transformer = mock_Transformer.return_value
        mock_pathtoaudio = mock_PathToAudio.return_value
        mock_controller = mock_Controller.return_value
        mock_audiomodulationlasercontrol.actual_samples_per_second = actual_samples_per_second
        mock_gcodereader.get_layers.return_value = fake_layers

        api = PrintAPI(self.DEFAULT_CONFIG)
        api.print_gcode(gcode_path, print_sub_layers = False)

        mock_Controller.assert_called_with(
            mock_audiomodulationlasercontrol,
            mock_pathtoaudio,
            mock_audiowriter,
            fake_layers,
            zaxis = mock_dripbasedzaxis,
            zaxis_control = None,
            status_call_back = None,
            max_lead_distance = self.DEFAULT_CONFIG['max_lead_distance_mm'],
            abort_on_error = True
            )
    def test_print_gcode_should_not_print_sublayers_if_option_flase(
        self,
        mock_SubLayerGenerator,
        mock_AudioDripZAxis,
        mock_AudioModulationLaserControl,
        mock_GCodeReader,
        mock_AudioWriter,
        mock_Transformer,
        mock_PathToAudio,
        mock_Controller,
    ):
        gcode_path = "FakeFile"
        actual_samples_per_second = 7
        fake_layers = "Fake Layers"
        mock_dripbasedzaxis = mock_AudioDripZAxis.return_value
        mock_audiomodulationlasercontrol = mock_AudioModulationLaserControl.return_value
        mock_gcodereader = mock_GCodeReader.return_value
        mock_sublayergenerator = mock_SubLayerGenerator.return_value
        mock_audiowriter = mock_AudioWriter.return_value
        mock_transformer = mock_Transformer.return_value
        mock_pathtoaudio = mock_PathToAudio.return_value
        mock_controller = mock_Controller.return_value
        mock_audiomodulationlasercontrol.actual_samples_per_second = actual_samples_per_second
        mock_gcodereader.get_layers.return_value = fake_layers

        api = PrintAPI(self.default_config)
        api.print_gcode(gcode_path, print_sub_layers=False)

        mock_Controller.assert_called_with(
            mock_audiomodulationlasercontrol,
            mock_pathtoaudio,
            mock_audiowriter,
            fake_layers,
            zaxis=mock_dripbasedzaxis,
            status_call_back=None,
            max_lead_distance=self.default_config.dripper.max_lead_distance_mm,
            abort_on_error=True)
    def initialize(self):
        self.grid()
        
        self._elapsed_time = StringVar()
        self._current_layer = IntVar()
        self._current_height = StringVar()
        self._current_model_height = StringVar()
        self._errors = IntVar()
        self._status = StringVar()
        self._stop_button_text = StringVar()
        self._stop_button_text.set("Abort Verification")
        self._current_status = {}

        self._print_api = PrintAPI(self.kwargs['config'],status_call_back = self.status_call_back)
        if 'filename' in self.kwargs:
            file_to_print = self.kwargs['filename']
            self._print_api.verify_gcode(file_to_print)
        else:
            self._print_api.verify_gcode(self.kwargs['layer_generator'])


        Label(self, text = "Verifying Model" ).grid(column=0,row=5)
        Label(self ).grid(column=0,row=8)

        Label(self, text = "Elapsed Time" ).grid(column=0,row=10)
        Label(self, textvariable = self._elapsed_time ).grid(column=1,row=10)

        Label(self, text = "Layer" ).grid(column=0,row=20)
        Label(self, textvariable = self._current_layer ).grid(column=1,row=20)

        Label(self, text = "Model Height (mm)" ).grid(column=0,row=35)
        Label(self, textvariable = self._current_model_height ).grid(column=1,row=35)

        Label(self, text = "Status").grid(column=0,row=60)
        Label(self, textvariable = self._status).grid(column=1,row=60)

        Label(self, text = "Errors" ).grid(column=0,row=70)
        Label(self, textvariable = self._errors ).grid(column=1,row=70)

        Label(self).grid(column=0,row=70)
        
        Button(self,textvariable=self._stop_button_text, command=self._stop_button_click).grid(column=2,row=80)
        Button(self,text="Show Errors", command=self._show_errors).grid(column=3,row=80)
        
        self.update()
    def test_get_status_calls_controller_status(
        self,
        mock_AudioDripZAxis,
        mock_AudioModulationLaserControl,
        mock_GCodeReader,
        mock_AudioWriter,
        mock_Transformer,
        mock_PathToAudio,
        mock_Controller,
    ):
        mock_audiomodulationlasercontrol = mock_AudioModulationLaserControl.return_value
        mock_audiomodulationlasercontrol.actual_samples_per_second = 7
        mock_controller = mock_Controller.return_value

        api = PrintAPI(self.default_config)
        api.print_gcode("Spam")
        api.get_status()

        mock_controller.get_status.assert_called_with()
    def test_set_drips_per_second_throws_error_if_not_using_emulated_drips(
        self,
        mock_SubLayerGenerator,
        mock_AudioDripZAxis,
        mock_AudioModulationLaserControl,
        mock_GCodeReader,
        mock_AudioWriter,
        mock_Transformer,
        mock_PathToAudio,
        mock_Controller,
    ):
        gcode_path = "FakeFile"

        mock_audiodripzaxis = mock_AudioDripZAxis.return_value
        mock_audiodripzaxis.set_drips_per_second.side_effect = Exception()

        config = self.default_config

        api = PrintAPI(config)
        api.print_gcode(gcode_path)

        with self.assertRaises(Exception):
            api.set_drips_per_second(12)
    def initialize(self):
        self.grid()
        self._print_api = None
        self._elapsed_time = StringVar()
        self._current_layer = IntVar()
        self._current_height = StringVar()
        self._current_model_height = StringVar()
        self._current_drips = IntVar()
        self._waiting_for_drips = StringVar()
        self._skipped_layers = IntVar()
        self._status = StringVar()
        self._stop_button_text = StringVar()
        self._stop_button_text.set("Abort Print")
        self._drips_per_second_setting = DoubleVar()

        Label(self, text = "Elapsed Time" ).grid(column=0,row=10)
        Label(self, textvariable = self._elapsed_time ).grid(column=1,row=10)

        Label(self, text = "Layer" ).grid(column=0,row=20)
        Label(self, textvariable = self._current_layer ).grid(column=1,row=20)

        Label(self, text = "Actual Height (mm)" ).grid(column=0,row=30)
        Label(self, textvariable = self._current_height ).grid(column=1,row=30)

        Label(self, text = "Model Height (mm)" ).grid(column=0,row=35)
        Label(self, textvariable = self._current_model_height ).grid(column=1,row=35)

        Label(self, text = "Drips" ).grid(column=0,row=40)
        Label(self, textvariable = self._current_drips ).grid(column=1,row=40)

        Label(self, text = "Waiting for drips" ).grid(column=0,row=50)
        Label(self, textvariable = self._waiting_for_drips ).grid(column=1,row=50)

        Label(self, text = "Skipped Layers" ).grid(column=0,row=55)
        Label(self, textvariable = self._skipped_layers ).grid(column=1,row=55)

        Label(self, text = "Status").grid(column=0,row=60)
        Label(self, textvariable = self._status).grid(column=1,row=60)

        self.options_frame = LabelFrame(self, text="In Print Options", padx=5, pady=5)
        self.options_frame.grid(column=12,row=10,rowspan = 60,sticky=N+S+E+W)
        self.options_frame.grid_remove()

        Label(self.options_frame, text = 'Drips Per Second').grid(column=0,row=10)
        RylanSpinbox(self.options_frame, from_=0.0, to=100.0, increment= 0.1, command = self._dps_changed, textvariable = self._drips_per_second_setting).grid(column=1,row=10)

        Label(self).grid(column=0,row=70)
        
        Button(self,textvariable=self._stop_button_text, command=self._stop_button_click).grid(column=2,row=80)

        self._print_api = PrintAPI(self.kwargs['config'],status_call_back = self.status_call_back)
        if 'filename' in self.kwargs:
            file_to_print = self.kwargs['filename']
            self._print_api.print_gcode(file_to_print)
        else:
            self._print_api.print_layers(self.kwargs['layer_generator'])
        if self._print_api.can_set_drips_per_second():
            self.options_frame.grid()
            self._drips_per_second_setting.set(self._print_api.get_drips_per_second())
        
        self.update()
class PrintStatusUI(PeachyFrame):

    def initialize(self):
        self.grid()
        self._print_api = None
        self._elapsed_time = StringVar()
        self._current_layer = IntVar()
        self._current_height = StringVar()
        self._current_model_height = StringVar()
        self._current_drips = IntVar()
        self._waiting_for_drips = StringVar()
        self._skipped_layers = IntVar()
        self._status = StringVar()
        self._stop_button_text = StringVar()
        self._stop_button_text.set("Abort Print")
        self._drips_per_second_setting = DoubleVar()

        Label(self, text = "Elapsed Time" ).grid(column=0,row=10)
        Label(self, textvariable = self._elapsed_time ).grid(column=1,row=10)

        Label(self, text = "Layer" ).grid(column=0,row=20)
        Label(self, textvariable = self._current_layer ).grid(column=1,row=20)

        Label(self, text = "Actual Height (mm)" ).grid(column=0,row=30)
        Label(self, textvariable = self._current_height ).grid(column=1,row=30)

        Label(self, text = "Model Height (mm)" ).grid(column=0,row=35)
        Label(self, textvariable = self._current_model_height ).grid(column=1,row=35)

        Label(self, text = "Drips" ).grid(column=0,row=40)
        Label(self, textvariable = self._current_drips ).grid(column=1,row=40)

        Label(self, text = "Waiting for drips" ).grid(column=0,row=50)
        Label(self, textvariable = self._waiting_for_drips ).grid(column=1,row=50)

        Label(self, text = "Skipped Layers" ).grid(column=0,row=55)
        Label(self, textvariable = self._skipped_layers ).grid(column=1,row=55)

        Label(self, text = "Status").grid(column=0,row=60)
        Label(self, textvariable = self._status).grid(column=1,row=60)

        self.options_frame = LabelFrame(self, text="In Print Options", padx=5, pady=5)
        self.options_frame.grid(column=12,row=10,rowspan = 60,sticky=N+S+E+W)
        self.options_frame.grid_remove()

        Label(self.options_frame, text = 'Drips Per Second').grid(column=0,row=10)
        RylanSpinbox(self.options_frame, from_=0.0, to=100.0, increment= 0.1, command = self._dps_changed, textvariable = self._drips_per_second_setting).grid(column=1,row=10)

        Label(self).grid(column=0,row=70)
        
        Button(self,textvariable=self._stop_button_text, command=self._stop_button_click).grid(column=2,row=80)

        self._print_api = PrintAPI(self.kwargs['config'],status_call_back = self.status_call_back)
        if 'filename' in self.kwargs:
            file_to_print = self.kwargs['filename']
            self._print_api.print_gcode(file_to_print)
        else:
            self._print_api.print_layers(self.kwargs['layer_generator'])
        if self._print_api.can_set_drips_per_second():
            self.options_frame.grid()
            self._drips_per_second_setting.set(self._print_api.get_drips_per_second())
        
        self.update()

    def _stop_button_click(self):
        self._print_api.stop()
        self.navigate(self.kwargs['calling_class'], printer = self.kwargs['printer'])

    def status_call_back(self,status):
        total_seconds = int(status['elapsed_time'].total_seconds())
        hours, remainder = divmod(total_seconds,60*60)
        minutes, seconds = divmod(remainder,60)

        self._elapsed_time.set("%02d:%02d:%02d" % (hours,minutes,seconds))
        self._current_layer.set(status['current_layer'])
        self._current_height.set("%.2f" % status['height'])
        self._current_model_height.set("%.2f" % status['model_height'])
        self._current_drips.set(status['drips'])
        self._waiting_for_drips.set("Yes" if status['waiting_for_drips'] else "No")
        self._skipped_layers.set(status['skipped_layers'])
        self._status.set(status['status'])
        if (status['status'] == "Complete"):
            self._stop_button_text.set("Finished")

    def _dps_changed(self):
        self._print_api.set_drips_per_second(self._drips_per_second_setting.get())

    def close(self):
        if self._print_api:
            self._print_api.stop()
 def test_print_can_be_stopped_before_started(self):
     api = PrintAPI(self.default_config)
     api.stop()
    def test_print_gcode_should_create_required_classes_and_start_it(
        self,
        mock_NullCommander,
        mock_SubLayerGenerator,
        mock_AudioDripZAxis,
        mock_AudioModulationLaserControl,
        mock_GCodeReader,
        mock_AudioWriter,
        mock_Transformer,
        mock_PathToAudio,
        mock_Controller,
    ):
        gcode_path = "FakeFile"
        actual_samples_per_second = 7
        fake_layers = "Fake Layers"
        mock_nullcommander = mock_NullCommander.return_value
        mock_dripbasedzaxis = mock_AudioDripZAxis.return_value
        mock_audiomodulationlasercontrol = mock_AudioModulationLaserControl.return_value
        mock_gcodereader = mock_GCodeReader.return_value
        mock_sublayergenerator = mock_SubLayerGenerator.return_value
        mock_audiowriter = mock_AudioWriter.return_value
        mock_transformer = mock_Transformer.return_value
        mock_pathtoaudio = mock_PathToAudio.return_value
        mock_controller = mock_Controller.return_value

        mock_audiomodulationlasercontrol.actual_samples_per_second = actual_samples_per_second
        mock_gcodereader.get_layers.return_value = fake_layers

        test_config = self.default_config

        api = PrintAPI(test_config)
        api.print_gcode(gcode_path)

        mock_SubLayerGenerator.assert_called_with(
            fake_layers, test_config.options.sublayer_height_mm)

        mock_AudioDripZAxis.assert_called_with(
            test_config.dripper.drips_per_mm,
            test_config.audio.input.sample_rate,
            test_config.audio.input.bit_depth, mock_nullcommander,
            test_config.serial.on_command, test_config.serial.off_command)
        mock_AudioModulationLaserControl.assert_called_with(
            test_config.audio.output.sample_rate,
            test_config.audio.output.modulation_on_frequency,
            test_config.audio.output.modulation_off_frequency,
            test_config.options.laser_offset)
        mock_GCodeReader.assert_called_with(gcode_path)
        mock_AudioWriter.assert_called_with(
            test_config.audio.output.sample_rate,
            test_config.audio.output.bit_depth,
        )
        mock_Transformer.assert_called_with(
            test_config.calibration.max_deflection,
            test_config.calibration.height,
            test_config.calibration.lower_points,
            test_config.calibration.upper_points,
        )
        mock_PathToAudio.assert_called_with(
            actual_samples_per_second, mock_transformer,
            test_config.options.laser_thickness_mm)
        mock_Controller.assert_called_with(
            mock_audiomodulationlasercontrol,
            mock_pathtoaudio,
            mock_audiowriter,
            mock_sublayergenerator,
            zaxis=mock_dripbasedzaxis,
            status_call_back=None,
            max_lead_distance=test_config.dripper.max_lead_distance_mm,
            abort_on_error=True)
 def test_print_can_be_stopped_before_started(self):
     api = PrintAPI(self.DEFAULT_CONFIG)
     api.stop()
 def test_print_can_be_stopped_before_started(self):
     api = PrintAPI(self.default_config)
     api.stop()
예제 #23
0
class PrintStatusUI(PeachyFrame):
    def initialize(self):
        self.grid()
        self._print_api = None
        self._elapsed_time = StringVar()
        self._current_layer = IntVar()
        self._current_height = StringVar()
        self._current_model_height = StringVar()
        self._current_drips = IntVar()
        self._waiting_for_drips = StringVar()
        self._skipped_layers = IntVar()
        self._status = StringVar()
        self._stop_button_text = StringVar()
        self._stop_button_text.set("Abort Print")
        self._drips_per_second_setting = DoubleVar()

        Label(self, text="Elapsed Time").grid(column=0, row=10)
        Label(self, textvariable=self._elapsed_time).grid(column=1, row=10)

        Label(self, text="Layer").grid(column=0, row=20)
        Label(self, textvariable=self._current_layer).grid(column=1, row=20)

        Label(self, text="Actual Height (mm)").grid(column=0, row=30)
        Label(self, textvariable=self._current_height).grid(column=1, row=30)

        Label(self, text="Model Height (mm)").grid(column=0, row=35)
        Label(self, textvariable=self._current_model_height).grid(column=1,
                                                                  row=35)

        Label(self, text="Drips").grid(column=0, row=40)
        Label(self, textvariable=self._current_drips).grid(column=1, row=40)

        Label(self, text="Waiting for drips").grid(column=0, row=50)
        Label(self, textvariable=self._waiting_for_drips).grid(column=1,
                                                               row=50)

        Label(self, text="Skipped Layers").grid(column=0, row=55)
        Label(self, textvariable=self._skipped_layers).grid(column=1, row=55)

        Label(self, text="Status").grid(column=0, row=60)
        Label(self, textvariable=self._status).grid(column=1, row=60)

        self.options_frame = LabelFrame(self,
                                        text="In Print Options",
                                        padx=5,
                                        pady=5)
        self.options_frame.grid(column=12,
                                row=10,
                                rowspan=60,
                                sticky=N + S + E + W)
        self.options_frame.grid_remove()

        Label(self.options_frame, text='Drips Per Second').grid(column=0,
                                                                row=10)
        RylanSpinbox(self.options_frame,
                     from_=0.0,
                     to=100.0,
                     increment=0.1,
                     command=self._dps_changed,
                     textvariable=self._drips_per_second_setting).grid(
                         column=1, row=10)

        Label(self).grid(column=0, row=70)

        Button(self,
               textvariable=self._stop_button_text,
               command=self._stop_button_click).grid(column=2, row=80)

        self._print_api = PrintAPI(self.kwargs['config'],
                                   status_call_back=self.status_call_back)
        if 'filename' in self.kwargs:
            file_to_print = self.kwargs['filename']
            self._print_api.print_gcode(file_to_print)
        else:
            self._print_api.print_layers(self.kwargs['layer_generator'])
        if self._print_api.can_set_drips_per_second():
            self.options_frame.grid()
            self._drips_per_second_setting.set(
                self._print_api.get_drips_per_second())

        self.update()

    def _stop_button_click(self):
        self._print_api.stop()
        self.navigate(self.kwargs['calling_class'],
                      printer=self.kwargs['printer'])

    def status_call_back(self, status):
        total_seconds = int(status['elapsed_time'].total_seconds())
        hours, remainder = divmod(total_seconds, 60 * 60)
        minutes, seconds = divmod(remainder, 60)

        self._elapsed_time.set("%02d:%02d:%02d" % (hours, minutes, seconds))
        self._current_layer.set(status['current_layer'])
        self._current_height.set("%.2f" % status['height'])
        self._current_model_height.set("%.2f" % status['model_height'])
        self._current_drips.set(status['drips'])
        self._waiting_for_drips.set(
            "Yes" if status['waiting_for_drips'] else "No")
        self._skipped_layers.set(status['skipped_layers'])
        self._status.set(status['status'])
        if (status['status'] == "Complete"):
            self._stop_button_text.set("Finished")

    def _dps_changed(self):
        self._print_api.set_drips_per_second(
            self._drips_per_second_setting.get())

    def close(self):
        if self._print_api:
            self._print_api.stop()
예제 #24
0
    def initialize(self):
        self.grid()
        self._print_api = None
        self._elapsed_time = StringVar()
        self._current_layer = IntVar()
        self._current_height = StringVar()
        self._current_model_height = StringVar()
        self._current_drips = IntVar()
        self._waiting_for_drips = StringVar()
        self._skipped_layers = IntVar()
        self._status = StringVar()
        self._stop_button_text = StringVar()
        self._stop_button_text.set("Abort Print")
        self._drips_per_second_setting = DoubleVar()

        Label(self, text="Elapsed Time").grid(column=0, row=10)
        Label(self, textvariable=self._elapsed_time).grid(column=1, row=10)

        Label(self, text="Layer").grid(column=0, row=20)
        Label(self, textvariable=self._current_layer).grid(column=1, row=20)

        Label(self, text="Actual Height (mm)").grid(column=0, row=30)
        Label(self, textvariable=self._current_height).grid(column=1, row=30)

        Label(self, text="Model Height (mm)").grid(column=0, row=35)
        Label(self, textvariable=self._current_model_height).grid(column=1,
                                                                  row=35)

        Label(self, text="Drips").grid(column=0, row=40)
        Label(self, textvariable=self._current_drips).grid(column=1, row=40)

        Label(self, text="Waiting for drips").grid(column=0, row=50)
        Label(self, textvariable=self._waiting_for_drips).grid(column=1,
                                                               row=50)

        Label(self, text="Skipped Layers").grid(column=0, row=55)
        Label(self, textvariable=self._skipped_layers).grid(column=1, row=55)

        Label(self, text="Status").grid(column=0, row=60)
        Label(self, textvariable=self._status).grid(column=1, row=60)

        self.options_frame = LabelFrame(self,
                                        text="In Print Options",
                                        padx=5,
                                        pady=5)
        self.options_frame.grid(column=12,
                                row=10,
                                rowspan=60,
                                sticky=N + S + E + W)
        self.options_frame.grid_remove()

        Label(self.options_frame, text='Drips Per Second').grid(column=0,
                                                                row=10)
        RylanSpinbox(self.options_frame,
                     from_=0.0,
                     to=100.0,
                     increment=0.1,
                     command=self._dps_changed,
                     textvariable=self._drips_per_second_setting).grid(
                         column=1, row=10)

        Label(self).grid(column=0, row=70)

        Button(self,
               textvariable=self._stop_button_text,
               command=self._stop_button_click).grid(column=2, row=80)

        self._print_api = PrintAPI(self.kwargs['config'],
                                   status_call_back=self.status_call_back)
        if 'filename' in self.kwargs:
            file_to_print = self.kwargs['filename']
            self._print_api.print_gcode(file_to_print)
        else:
            self._print_api.print_layers(self.kwargs['layer_generator'])
        if self._print_api.can_set_drips_per_second():
            self.options_frame.grid()
            self._drips_per_second_setting.set(
                self._print_api.get_drips_per_second())

        self.update()
    def test_verify_gcode_should_create_required_classes_and_start_it_and_return_errors(self,
            mock_SubLayerGenerator, 
            mock_AudioDripZAxis,
            mock_AudioModulationLaserControl,
            mock_GCodeReader,
            mock_AudioWriter,
            mock_Transformer,
            mock_PathToAudio,
            mock_Controller,
            ):
        gcode_path = "FakeFile"
        actual_samples_per_second = 7
        fake_layers = "Fake Layers"
        mock_dripbasedzaxis = mock_AudioDripZAxis.return_value
        mock_audiomodulationlasercontrol = mock_AudioModulationLaserControl.return_value
        mock_gcodereader = mock_GCodeReader.return_value
        mock_sublayergenerator = mock_SubLayerGenerator.return_value
        mock_audiowriter = mock_AudioWriter.return_value
        mock_transformer = mock_Transformer.return_value
        mock_pathtoaudio = mock_PathToAudio.return_value
        mock_controller = mock_Controller.return_value
        expected_errors = ['Some Error']
        mock_controller.get_status.return_value = {'errors':expected_errors}

        mock_audiomodulationlasercontrol.actual_samples_per_second = actual_samples_per_second
        mock_gcodereader.get_layers.return_value = fake_layers

        test_config = self.default_config
        api = PrintAPI(test_config)
        api.verify_gcode(gcode_path)


        mock_SubLayerGenerator.assert_called_with(
            fake_layers,
            test_config.options.sublayer_height_mm
            )

        self.assertEquals(0, mock_AudioDripZAxis.call_count)
        mock_AudioModulationLaserControl.assert_called_with(
            test_config.audio.output.sample_rate,
            test_config.audio.output.modulation_on_frequency,
            test_config.audio.output.modulation_off_frequency,
            test_config.options.laser_offset
            )
        mock_GCodeReader.assert_called_with(gcode_path)

        self.assertEquals(0, mock_AudioWriter.call_count)

        mock_Transformer.assert_called_with(
            test_config.calibration.max_deflection,
            test_config.calibration.height,
            test_config.calibration.lower_points,
            test_config.calibration.upper_points,
            )
        mock_PathToAudio.assert_called_with(
            actual_samples_per_second,
            mock_transformer, 
            test_config.options.laser_thickness_mm
            )
        mock_Controller.assert_called_with(
            mock_audiomodulationlasercontrol,
            mock_pathtoaudio,
            None,
            mock_sublayergenerator,
            zaxis = None,
            status_call_back = None,
            max_lead_distance = test_config.dripper.max_lead_distance_mm,
            abort_on_error = False
            )
예제 #26
0
class PrintStatusUI(PeachyFrame):

    def initialize(self):
        self.grid()
        
        self._elapsed_time = StringVar()
        self._current_layer = IntVar()
        self._current_height = StringVar()
        self._current_model_height = StringVar()
        self._current_drips = IntVar()
        self._waiting_for_drips = StringVar()
        self._skipped_layers = IntVar()
        self._status = StringVar()
        self._stop_button_text = StringVar()
        self._stop_button_text.set("Abort Print")

        self._print_api = PrintAPI(self.kwargs['config'],status_call_back = self.status_call_back)
        if 'filename' in self.kwargs:
            file_to_print = self.kwargs['filename']
            self._print_api.print_gcode(file_to_print)
        else:
            self._print_api.print_layers(self.kwargs['layer_generator'])


        Label(self, text = "Elapsed Time" ).grid(column=0,row=10)
        Label(self, textvariable = self._elapsed_time ).grid(column=1,row=10)

        Label(self, text = "Layer" ).grid(column=0,row=20)
        Label(self, textvariable = self._current_layer ).grid(column=1,row=20)

        Label(self, text = "Actual Height (mm)" ).grid(column=0,row=30)
        Label(self, textvariable = self._current_height ).grid(column=1,row=30)

        Label(self, text = "Model Height (mm)" ).grid(column=0,row=35)
        Label(self, textvariable = self._current_model_height ).grid(column=1,row=35)

        Label(self, text = "Drips" ).grid(column=0,row=40)
        Label(self, textvariable = self._current_drips ).grid(column=1,row=40)

        Label(self, text = "Waiting for drips" ).grid(column=0,row=50)
        Label(self, textvariable = self._waiting_for_drips ).grid(column=1,row=50)

        Label(self, text = "Skipped Layers" ).grid(column=0,row=55)
        Label(self, textvariable = self._skipped_layers ).grid(column=1,row=55)

        Label(self, text = "Status").grid(column=0,row=60)
        Label(self, textvariable = self._status).grid(column=1,row=60)

        Label(self).grid(column=0,row=70)
        
        Button(self,textvariable=self._stop_button_text, command=self._stop_button_click).grid(column=2,row=80)
        
        self.update()

    def _stop_button_click(self):
        self._print_api.stop()
        self.navigate(self.kwargs['calling_class'], printer = self.kwargs['printer'])

    def status_call_back(self,status):
        total_seconds = int(status['elapsed_time'].total_seconds())
        hours, remainder = divmod(total_seconds,60*60)
        minutes, seconds = divmod(remainder,60)

        self._elapsed_time.set("%02d:%02d:%02d" % (hours,minutes,seconds))
        self._current_layer.set(status['current_layer'])
        self._current_height.set("%.2f" % status['height'])
        self._current_model_height.set("%.2f" % status['model_height'])
        self._current_drips.set(status['drips'])
        self._waiting_for_drips.set("Yes" if status['waiting_for_drips'] else "No")
        self._skipped_layers.set(status['skipped_layers'])
        self._status.set(status['status'])
        if (status['status'] == "Complete"):
            self._stop_button_text.set("Finished")

    def close(self):
        self._print_api.stop()
    def test_print_gcode_should_create_required_classes_and_start_it(self,
            mock_SubLayerGenerator, 
            mock_DripBasedZAxis,
            mock_AudioModulationLaserControl,
            mock_GCodeReader,
            mock_AudioWriter,
            mock_Transformer,
            mock_PathToAudio,
            mock_Controller,
            ):
        gcode_path = "FakeFile"
        actual_samples_per_second = 7
        fake_layers = "Fake Layers"
        mock_dripbasedzaxis = mock_DripBasedZAxis.return_value
        mock_audiomodulationlasercontrol = mock_AudioModulationLaserControl.return_value
        mock_gcodereader = mock_GCodeReader.return_value
        mock_sublayergenerator = mock_SubLayerGenerator.return_value
        mock_audiowriter = mock_AudioWriter.return_value
        mock_transformer = mock_Transformer.return_value
        mock_pathtoaudio = mock_PathToAudio.return_value
        mock_controller = mock_Controller.return_value

        mock_audiomodulationlasercontrol.actual_samples_per_second = actual_samples_per_second
        mock_gcodereader.get_layers.return_value = fake_layers


        api = PrintAPI(self.DEFAULT_CONFIG)
        api.print_gcode(gcode_path)

        mock_SubLayerGenerator.assert_called_with(
            fake_layers,
            self.DEFAULT_CONFIG['sublayer_height_mm']
            )

        mock_DripBasedZAxis.assert_called_with(
            drips_per_mm = self.DEFAULT_CONFIG['drips_per_mm'],
            initial_height = 0.0,
            sample_rate =  self.DEFAULT_CONFIG['input_sample_frequency'],
            bit_depth = self.DEFAULT_CONFIG['input_bit_depth']
            )
        mock_AudioModulationLaserControl.assert_called_with(
            self.DEFAULT_CONFIG['output_sample_frequency'],
            self.DEFAULT_CONFIG['on_modulation_frequency'],
            self.DEFAULT_CONFIG['off_modulation_frequency'],
            )
        mock_GCodeReader.assert_called_with(gcode_path)
        mock_AudioWriter.assert_called_with(
            self.DEFAULT_CONFIG['output_sample_frequency'],
            self.DEFAULT_CONFIG['output_bit_depth'],
            )
        mock_Transformer.assert_called_with(self.DEFAULT_CONFIG['calibration_data'], scale = self.DEFAULT_CONFIG['max_deflection'])
        mock_PathToAudio.assert_called_with(
            actual_samples_per_second,
            mock_transformer, 
            self.DEFAULT_CONFIG['laser_thickness_mm']
            )
        mock_Controller.assert_called_with(
            mock_audiomodulationlasercontrol,
            mock_pathtoaudio,
            mock_audiowriter,
            mock_sublayergenerator,
            zaxis = mock_dripbasedzaxis,
            zaxis_control = None,
            status_call_back = None,
            max_lead_distance = self.DEFAULT_CONFIG['max_lead_distance_mm'],
            abort_on_error = True
            )
예제 #28
0
class VerifyStatusUI(PeachyFrame):
    def initialize(self):
        self.grid()

        self._elapsed_time = StringVar()
        self._current_layer = IntVar()
        self._current_height = StringVar()
        self._current_model_height = StringVar()
        self._errors = IntVar()
        self._status = StringVar()
        self._stop_button_text = StringVar()
        self._stop_button_text.set("Abort Verification")
        self._current_status = {}

        self._print_api = PrintAPI(self.kwargs['config'],
                                   status_call_back=self.status_call_back)
        if 'filename' in self.kwargs:
            file_to_print = self.kwargs['filename']
            self._print_api.verify_gcode(file_to_print)
        else:
            self._print_api.verify_gcode(self.kwargs['layer_generator'])

        Label(self, text="Verifying Model").grid(column=0, row=5)
        Label(self).grid(column=0, row=8)

        Label(self, text="Elapsed Time").grid(column=0, row=10)
        Label(self, textvariable=self._elapsed_time).grid(column=1, row=10)

        Label(self, text="Layer").grid(column=0, row=20)
        Label(self, textvariable=self._current_layer).grid(column=1, row=20)

        Label(self, text="Model Height (mm)").grid(column=0, row=35)
        Label(self, textvariable=self._current_model_height).grid(column=1,
                                                                  row=35)

        Label(self, text="Status").grid(column=0, row=60)
        Label(self, textvariable=self._status).grid(column=1, row=60)

        Label(self, text="Errors").grid(column=0, row=70)
        Label(self, textvariable=self._errors).grid(column=1, row=70)

        Label(self).grid(column=0, row=70)

        Button(self,
               textvariable=self._stop_button_text,
               command=self._stop_button_click).grid(column=2, row=80)
        Button(self, text="Show Errors",
               command=self._show_errors).grid(column=3, row=80)

        self.update()

    def _stop_button_click(self):
        self._print_api.stop()
        self.navigate(self.kwargs['calling_class'],
                      printer=self.kwargs['printer'])

    def _show_errors(self):
        PopUp(
            self, 'Errors', '\n'.join([
                "SubLayer %s : %s" % (err['layer'], err['message'])
                for err in self._current_status['errors']
            ]))

    def status_call_back(self, status):
        total_seconds = int(status['elapsed_time'].total_seconds())
        hours, remainder = divmod(total_seconds, 60 * 60)
        minutes, seconds = divmod(remainder, 60)

        self._elapsed_time.set("%02d:%02d:%02d" % (hours, minutes, seconds))
        self._current_layer.set(status['current_layer'])
        self._current_model_height.set("%.2f" % status['model_height'])
        self._errors.set(len(status['errors']))
        self._current_status = status
        self._status.set(status['status'])
        if (status['status'] == "Complete"):
            self._stop_button_text.set("Finished")

    def close(self):
        self._print_api.stop()
class VerifyStatusUI(PeachyFrame):

    def initialize(self):
        self.grid()
        
        self._elapsed_time = StringVar()
        self._current_layer = IntVar()
        self._current_height = StringVar()
        self._current_model_height = StringVar()
        self._errors = IntVar()
        self._status = StringVar()
        self._stop_button_text = StringVar()
        self._stop_button_text.set("Abort Verification")
        self._current_status = {}

        self._print_api = PrintAPI(self.kwargs['config'],status_call_back = self.status_call_back)
        if 'filename' in self.kwargs:
            file_to_print = self.kwargs['filename']
            self._print_api.verify_gcode(file_to_print)
        else:
            self._print_api.verify_gcode(self.kwargs['layer_generator'])


        Label(self, text = "Verifying Model" ).grid(column=0,row=5)
        Label(self ).grid(column=0,row=8)

        Label(self, text = "Elapsed Time" ).grid(column=0,row=10)
        Label(self, textvariable = self._elapsed_time ).grid(column=1,row=10)

        Label(self, text = "Layer" ).grid(column=0,row=20)
        Label(self, textvariable = self._current_layer ).grid(column=1,row=20)

        Label(self, text = "Model Height (mm)" ).grid(column=0,row=35)
        Label(self, textvariable = self._current_model_height ).grid(column=1,row=35)

        Label(self, text = "Status").grid(column=0,row=60)
        Label(self, textvariable = self._status).grid(column=1,row=60)

        Label(self, text = "Errors" ).grid(column=0,row=70)
        Label(self, textvariable = self._errors ).grid(column=1,row=70)

        Label(self).grid(column=0,row=70)
        
        Button(self,textvariable=self._stop_button_text, command=self._stop_button_click).grid(column=2,row=80)
        Button(self,text="Show Errors", command=self._show_errors).grid(column=3,row=80)
        
        self.update()

    def _stop_button_click(self):
        self._print_api.stop()
        self.navigate(self.kwargs['calling_class'], printer = self.kwargs['printer'])

    def _show_errors(self):
        PopUp(self,'Errors', '\n'.join([ "SubLayer %s : %s" % (err['layer'], err['message']) for err in self._current_status['errors'] ]))

    def status_call_back(self,status):
        total_seconds = int(status['elapsed_time'].total_seconds())
        hours, remainder = divmod(total_seconds,60*60)
        minutes, seconds = divmod(remainder,60)

        self._elapsed_time.set("%02d:%02d:%02d" % (hours,minutes,seconds))
        self._current_layer.set(status['current_layer'])
        self._current_model_height.set("%.2f" % status['model_height'])
        self._errors.set(len(status['errors']))
        self._current_status = status
        self._status.set(status['status'])
        if (status['status'] == "Complete"):
            self._stop_button_text.set("Finished")

    def close(self):
        self._print_api.stop()
    def test_print_gcode_should_create_required_classes_and_start_it(self,
            mock_NullCommander,
            mock_SubLayerGenerator, 
            mock_AudioDripZAxis,
            mock_AudioModulationLaserControl,
            mock_GCodeReader,
            mock_AudioWriter,
            mock_Transformer,
            mock_PathToAudio,
            mock_Controller,
            ):
        gcode_path = "FakeFile"
        actual_samples_per_second = 7
        fake_layers = "Fake Layers"
        mock_nullcommander = mock_NullCommander.return_value
        mock_dripbasedzaxis = mock_AudioDripZAxis.return_value
        mock_audiomodulationlasercontrol = mock_AudioModulationLaserControl.return_value
        mock_gcodereader = mock_GCodeReader.return_value
        mock_sublayergenerator = mock_SubLayerGenerator.return_value
        mock_audiowriter = mock_AudioWriter.return_value
        mock_transformer = mock_Transformer.return_value
        mock_pathtoaudio = mock_PathToAudio.return_value
        mock_controller = mock_Controller.return_value

        mock_audiomodulationlasercontrol.actual_samples_per_second = actual_samples_per_second
        mock_gcodereader.get_layers.return_value = fake_layers

        test_config = self.default_config

        api = PrintAPI(test_config)
        api.print_gcode(gcode_path)

        mock_SubLayerGenerator.assert_called_with(
            fake_layers,
            test_config.options.sublayer_height_mm
            )

        mock_AudioDripZAxis.assert_called_with(
            test_config.dripper.drips_per_mm,
            test_config.audio.input.sample_rate,
            test_config.audio.input.bit_depth,
            mock_nullcommander,
            test_config.serial.on_command,
            test_config.serial.off_command
            )
        mock_AudioModulationLaserControl.assert_called_with(
            test_config.audio.output.sample_rate,
            test_config.audio.output.modulation_on_frequency,
            test_config.audio.output.modulation_off_frequency,
            test_config.options.laser_offset
            )
        mock_GCodeReader.assert_called_with(gcode_path)
        mock_AudioWriter.assert_called_with(
            test_config.audio.output.sample_rate,
            test_config.audio.output.bit_depth,
            )
        mock_Transformer.assert_called_with(
            test_config.calibration.max_deflection,
            test_config.calibration.height,
            test_config.calibration.lower_points,
            test_config.calibration.upper_points,
            )
        mock_PathToAudio.assert_called_with(
            actual_samples_per_second,
            mock_transformer, 
            test_config.options.laser_thickness_mm
            )
        mock_Controller.assert_called_with(
            mock_audiomodulationlasercontrol,
            mock_pathtoaudio,
            mock_audiowriter,
            mock_sublayergenerator,
            zaxis = mock_dripbasedzaxis,
            status_call_back = None,
            max_lead_distance = test_config.dripper.max_lead_distance_mm,
            abort_on_error = True
            )
    def test_verify_gcode_should_create_required_classes_and_start_it_and_return_errors(
        self,
        mock_SubLayerGenerator,
        mock_AudioDripZAxis,
        mock_AudioModulationLaserControl,
        mock_GCodeReader,
        mock_AudioWriter,
        mock_Transformer,
        mock_PathToAudio,
        mock_Controller,
    ):
        gcode_path = "FakeFile"
        actual_samples_per_second = 7
        fake_layers = "Fake Layers"
        mock_dripbasedzaxis = mock_AudioDripZAxis.return_value
        mock_audiomodulationlasercontrol = mock_AudioModulationLaserControl.return_value
        mock_gcodereader = mock_GCodeReader.return_value
        mock_sublayergenerator = mock_SubLayerGenerator.return_value
        mock_audiowriter = mock_AudioWriter.return_value
        mock_transformer = mock_Transformer.return_value
        mock_pathtoaudio = mock_PathToAudio.return_value
        mock_controller = mock_Controller.return_value
        expected_errors = ['Some Error']
        mock_controller.get_status.return_value = {'errors': expected_errors}

        mock_audiomodulationlasercontrol.actual_samples_per_second = actual_samples_per_second
        mock_gcodereader.get_layers.return_value = fake_layers

        test_config = self.default_config
        api = PrintAPI(test_config)
        api.verify_gcode(gcode_path)

        mock_SubLayerGenerator.assert_called_with(
            fake_layers, test_config.options.sublayer_height_mm)

        self.assertEquals(0, mock_AudioDripZAxis.call_count)
        mock_AudioModulationLaserControl.assert_called_with(
            test_config.audio.output.sample_rate,
            test_config.audio.output.modulation_on_frequency,
            test_config.audio.output.modulation_off_frequency,
            test_config.options.laser_offset)
        mock_GCodeReader.assert_called_with(gcode_path)

        self.assertEquals(0, mock_AudioWriter.call_count)

        mock_Transformer.assert_called_with(
            test_config.calibration.max_deflection,
            test_config.calibration.height,
            test_config.calibration.lower_points,
            test_config.calibration.upper_points,
        )
        mock_PathToAudio.assert_called_with(
            actual_samples_per_second, mock_transformer,
            test_config.options.laser_thickness_mm)
        mock_Controller.assert_called_with(
            mock_audiomodulationlasercontrol,
            mock_pathtoaudio,
            None,
            mock_sublayergenerator,
            zaxis=None,
            status_call_back=None,
            max_lead_distance=test_config.dripper.max_lead_distance_mm,
            abort_on_error=False)
    def test_verify_gcode_should_create_required_classes_and_start_it_and_return_errors(self,
            mock_SubLayerGenerator, 
            mock_DripBasedZAxis,
            mock_AudioModulationLaserControl,
            mock_GCodeReader,
            mock_AudioWriter,
            mock_Transformer,
            mock_PathToAudio,
            mock_Controller,
            ):
        gcode_path = "FakeFile"
        actual_samples_per_second = 7
        fake_layers = "Fake Layers"
        mock_dripbasedzaxis = mock_DripBasedZAxis.return_value
        mock_audiomodulationlasercontrol = mock_AudioModulationLaserControl.return_value
        mock_gcodereader = mock_GCodeReader.return_value
        mock_sublayergenerator = mock_SubLayerGenerator.return_value
        mock_audiowriter = mock_AudioWriter.return_value
        mock_transformer = mock_Transformer.return_value
        mock_pathtoaudio = mock_PathToAudio.return_value
        mock_controller = mock_Controller.return_value
        expected_errors = ['Some Error']
        mock_controller.get_status.return_value = {'errors':expected_errors}

        mock_audiomodulationlasercontrol.actual_samples_per_second = actual_samples_per_second
        mock_gcodereader.get_layers.return_value = fake_layers


        api = PrintAPI(self.DEFAULT_CONFIG)
        api.verify_gcode(gcode_path)


        mock_SubLayerGenerator.assert_called_with(
            fake_layers,
            self.DEFAULT_CONFIG['sublayer_height_mm']
            )

        self.assertEquals(0, mock_DripBasedZAxis.call_count)
        mock_AudioModulationLaserControl.assert_called_with(
            self.DEFAULT_CONFIG['output_sample_frequency'],
            self.DEFAULT_CONFIG['on_modulation_frequency'],
            self.DEFAULT_CONFIG['off_modulation_frequency'],
            )
        mock_GCodeReader.assert_called_with(gcode_path)

        self.assertEquals(0, mock_AudioWriter.call_count)

        mock_Transformer.assert_called_with(self.DEFAULT_CONFIG['calibration_data'], scale = self.DEFAULT_CONFIG['max_deflection'])
        mock_PathToAudio.assert_called_with(
            actual_samples_per_second,
            mock_transformer, 
            self.DEFAULT_CONFIG['laser_thickness_mm']
            )
        mock_Controller.assert_called_with(
            mock_audiomodulationlasercontrol,
            mock_pathtoaudio,
            None,
            mock_sublayergenerator,
            zaxis = None,
            zaxis_control = None,
            status_call_back = None,
            max_lead_distance = self.DEFAULT_CONFIG['max_lead_distance_mm'],
            abort_on_error = False
            )