Handle log, temperatures. Move controller to main tabpanel. More things
This commit is contained in:
parent
3ab4d4b094
commit
9af43bee52
@ -9,7 +9,7 @@ use Slic3r::GUI::AboutDialog;
|
||||
use Slic3r::GUI::BedShapeDialog;
|
||||
use Slic3r::GUI::BonjourBrowser;
|
||||
use Slic3r::GUI::ConfigWizard;
|
||||
use Slic3r::GUI::Controller::Frame;
|
||||
use Slic3r::GUI::Controller;
|
||||
use Slic3r::GUI::Controller::PrinterPanel;
|
||||
use Slic3r::GUI::MainFrame;
|
||||
use Slic3r::GUI::Notifier;
|
||||
@ -295,14 +295,6 @@ sub CallAfter {
|
||||
push @cb, $cb;
|
||||
}
|
||||
|
||||
sub show_printer_controller {
|
||||
my ($self) = @_;
|
||||
|
||||
$self->{controller_frame} //= Slic3r::GUI::Controller::Frame->new;
|
||||
$self->{controller_frame}->Show;
|
||||
return $self->{controller_frame};
|
||||
}
|
||||
|
||||
sub scan_serial_ports {
|
||||
my ($self) = @_;
|
||||
|
||||
|
@ -1,17 +1,17 @@
|
||||
package Slic3r::GUI::Controller::Frame;
|
||||
package Slic3r::GUI::Controller;
|
||||
use strict;
|
||||
use warnings;
|
||||
use utf8;
|
||||
|
||||
use Wx qw(wxTheApp :frame :id :misc :sizer :bitmap :button);
|
||||
use Wx::Event qw(EVT_CLOSE EVT_LEFT_DOWN EVT_MENU);
|
||||
use base 'Wx::Frame';
|
||||
use base 'Wx::ScrolledWindow';
|
||||
|
||||
sub new {
|
||||
my ($class) = @_;
|
||||
my $self = $class->SUPER::new(undef, -1, "Controller", wxDefaultPosition, [600,350],
|
||||
wxDEFAULT_FRAME_STYLE | wxFRAME_EX_METAL);
|
||||
my ($class, $parent) = @_;
|
||||
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, [600,350]);
|
||||
|
||||
$self->SetScrollbars(0, 1, 0, 1);
|
||||
$self->{sizer} = my $sizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||
|
||||
{
|
@ -3,15 +3,17 @@ use strict;
|
||||
use warnings;
|
||||
use utf8;
|
||||
|
||||
use Wx qw(wxTheApp :panel :id :misc :sizer :button :bitmap :window :gauge :timer);
|
||||
use Wx qw(wxTheApp :panel :id :misc :sizer :button :bitmap :window :gauge :timer
|
||||
:textctrl :font :systemsettings);
|
||||
use Wx::Event qw(EVT_BUTTON EVT_MOUSEWHEEL EVT_TIMER);
|
||||
use base qw(Wx::Panel Class::Accessor);
|
||||
|
||||
__PACKAGE__->mk_accessors(qw(printer_name config sender jobs
|
||||
printing print_status_timer));
|
||||
printing status_timer temp_timer));
|
||||
|
||||
use constant CONNECTION_TIMEOUT => 3; # seconds
|
||||
use constant PRINT_STATUS_TIMER_INTERVAL => 1000; # milliseconds
|
||||
use constant STATUS_TIMER_INTERVAL => 1000; # milliseconds
|
||||
use constant TEMP_TIMER_INTERVAL => 5000; # milliseconds
|
||||
|
||||
sub new {
|
||||
my ($class, $parent, $printer_name, $config) = @_;
|
||||
@ -21,20 +23,51 @@ sub new {
|
||||
$self->config($config);
|
||||
$self->jobs([]);
|
||||
|
||||
# set up the timer that polls for updates
|
||||
{
|
||||
my $timer_id = &Wx::NewId();
|
||||
$self->print_status_timer(Wx::Timer->new($self, $timer_id));
|
||||
$self->status_timer(Wx::Timer->new($self, $timer_id));
|
||||
EVT_TIMER($self, $timer_id, sub {
|
||||
my ($self, $event) = @_;
|
||||
|
||||
return if !$self->printing;
|
||||
if ($self->printing) {
|
||||
my $queue_size = $self->sender->queue_size;
|
||||
$self->{gauge}->SetValue($self->{gauge}->GetRange - $queue_size);
|
||||
if ($queue_size == 0) {
|
||||
$self->print_completed;
|
||||
return;
|
||||
}
|
||||
# TODO: get temperature messages
|
||||
}
|
||||
$self->{log_textctrl}->AppendText("$_\n") for @{$self->sender->purge_log};
|
||||
{
|
||||
my $temp = $self->sender->getT;
|
||||
if ($temp eq '') {
|
||||
$self->{temp_panel}->Hide;
|
||||
} else {
|
||||
if (!$self->{temp_panel}->IsShown) {
|
||||
$self->{temp_panel}->Show;
|
||||
$self->Layout;
|
||||
}
|
||||
$self->{temp_text}->SetLabel($temp . "°C");
|
||||
|
||||
$temp = $self->sender->getB;
|
||||
if ($temp eq '') {
|
||||
$self->{bed_temp_text}->SetLabel('n.a.');
|
||||
} else {
|
||||
$self->{bed_temp_text}->SetLabel($temp . "°C");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
# set up the timer that sends temperature requests
|
||||
# (responses are handled by status_timer)
|
||||
{
|
||||
my $timer_id = &Wx::NewId();
|
||||
$self->temp_timer(Wx::Timer->new($self, $timer_id));
|
||||
EVT_TIMER($self, $timer_id, sub {
|
||||
my ($self, $event) = @_;
|
||||
$self->sender->send("M105", 1); # send it through priority queue
|
||||
});
|
||||
}
|
||||
|
||||
@ -44,7 +77,7 @@ sub new {
|
||||
|
||||
# printer name
|
||||
{
|
||||
my $text = Wx::StaticText->new($box, -1, $self->printer_name, wxDefaultPosition, [250,-1]);
|
||||
my $text = Wx::StaticText->new($box, -1, $self->printer_name, wxDefaultPosition, [220,-1]);
|
||||
my $font = $text->GetFont;
|
||||
$font->SetPointSize(20);
|
||||
$text->SetFont($font);
|
||||
@ -105,7 +138,7 @@ sub new {
|
||||
|
||||
# buttons
|
||||
{
|
||||
$self->{btn_connect} = my $btn = Wx::Button->new($box, -1, "Connect", wxDefaultPosition, [-1, 40]);
|
||||
$self->{btn_connect} = my $btn = Wx::Button->new($box, -1, "Connect to printer", wxDefaultPosition, [-1, 40]);
|
||||
my $font = $btn->GetFont;
|
||||
$font->SetPointSize($font->GetPointSize + 2);
|
||||
$btn->SetFont($font);
|
||||
@ -124,8 +157,40 @@ sub new {
|
||||
}
|
||||
|
||||
# status
|
||||
$self->{status_text} = Wx::StaticText->new($box, -1, "", wxDefaultPosition, [250,-1]);
|
||||
$left_sizer->Add($self->{status_text}, 0, wxEXPAND | wxTOP, 15);
|
||||
$self->{status_text} = Wx::StaticText->new($box, -1, "", wxDefaultPosition, [200,-1]);
|
||||
$left_sizer->Add($self->{status_text}, 1, wxEXPAND | wxTOP, 15);
|
||||
|
||||
# temperature
|
||||
{
|
||||
my $temp_panel = $self->{temp_panel} = Wx::Panel->new($box, -1);
|
||||
my $temp_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||
|
||||
my $temp_font = Wx::Font->new($Slic3r::GUI::small_font);
|
||||
$temp_font->SetWeight(wxFONTWEIGHT_BOLD);
|
||||
{
|
||||
my $text = Wx::StaticText->new($temp_panel, -1, "Temperature:", wxDefaultPosition, wxDefaultSize);
|
||||
$text->SetFont($Slic3r::GUI::small_font);
|
||||
$temp_sizer->Add($text, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
$self->{temp_text} = Wx::StaticText->new($temp_panel, -1, "", wxDefaultPosition, wxDefaultSize);
|
||||
$self->{temp_text}->SetFont($temp_font);
|
||||
$self->{temp_text}->SetForegroundColour(Wx::wxRED);
|
||||
$temp_sizer->Add($self->{temp_text}, 1, wxALIGN_CENTER_VERTICAL);
|
||||
}
|
||||
{
|
||||
my $text = Wx::StaticText->new($temp_panel, -1, "Bed:", wxDefaultPosition, wxDefaultSize);
|
||||
$text->SetFont($Slic3r::GUI::small_font);
|
||||
$temp_sizer->Add($text, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
$self->{bed_temp_text} = Wx::StaticText->new($temp_panel, -1, "", wxDefaultPosition, wxDefaultSize);
|
||||
$self->{bed_temp_text}->SetFont($temp_font);
|
||||
$self->{bed_temp_text}->SetForegroundColour(Wx::wxRED);
|
||||
$temp_sizer->Add($self->{bed_temp_text}, 1, wxALIGN_CENTER_VERTICAL);
|
||||
}
|
||||
$temp_panel->SetSizer($temp_sizer);
|
||||
$temp_panel->Hide;
|
||||
$left_sizer->Add($temp_panel, 0, wxEXPAND | wxTOP, 4);
|
||||
}
|
||||
|
||||
# print jobs panel
|
||||
my $print_jobs_sizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||
@ -141,14 +206,27 @@ sub new {
|
||||
$print_jobs_sizer->Add($self->{jobs_panel}, 1, wxEXPAND, 0);
|
||||
}
|
||||
|
||||
my $log_sizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||
{
|
||||
my $text = Wx::StaticText->new($box, -1, "Log:", wxDefaultPosition, wxDefaultSize);
|
||||
$text->SetFont($Slic3r::GUI::small_font);
|
||||
$log_sizer->Add($text, 0, wxEXPAND, 0);
|
||||
|
||||
my $log = $self->{log_textctrl} = Wx::TextCtrl->new($box, -1, "", wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxBORDER_SUNKEN);
|
||||
$log->SetBackgroundColour($box->GetBackgroundColour);
|
||||
$log->SetFont($Slic3r::GUI::small_font);
|
||||
$log->SetEditable(0);
|
||||
$log_sizer->Add($self->{log_textctrl}, 1, wxEXPAND, 0);
|
||||
}
|
||||
|
||||
$sizer->Add($left_sizer, 0, wxEXPAND | wxALL, 0);
|
||||
$sizer->Add($print_jobs_sizer, 1, wxEXPAND | wxALL, 0);
|
||||
$sizer->Add($print_jobs_sizer, 2, wxEXPAND | wxALL, 0);
|
||||
$sizer->Add($log_sizer, 1, wxEXPAND | wxLEFT, 15);
|
||||
|
||||
$self->SetSizer($sizer);
|
||||
$self->SetMinSize($self->GetSize);
|
||||
|
||||
$self->_update_connection_controls;
|
||||
$self->set_status('Printer is offline. Click the Connect button.');
|
||||
|
||||
return $self;
|
||||
}
|
||||
@ -183,7 +261,7 @@ sub _update_connection_controls {
|
||||
sub set_status {
|
||||
my ($self, $status) = @_;
|
||||
$self->{status_text}->SetLabel($status);
|
||||
$self->{status_text}->Wrap($self->{status_text}->GetSize->GetWidth - 30);
|
||||
$self->{status_text}->Wrap($self->{status_text}->GetSize->GetWidth);
|
||||
$self->{status_text}->Refresh;
|
||||
$self->Layout;
|
||||
}
|
||||
@ -209,6 +287,11 @@ sub connect {
|
||||
}
|
||||
if ($self->sender->is_connected) {
|
||||
$self->set_status("Printer is online. You can now start printing from the queue on the right.");
|
||||
$self->status_timer->Start(STATUS_TIMER_INTERVAL, wxTIMER_CONTINUOUS);
|
||||
$self->temp_timer->Start(TEMP_TIMER_INTERVAL, wxTIMER_CONTINUOUS);
|
||||
|
||||
# request temperature now, without waiting for the timer
|
||||
$self->sender->send("M105", 1);
|
||||
} else {
|
||||
$self->set_status("Connection failed. Check serial port and speed.");
|
||||
}
|
||||
@ -219,14 +302,16 @@ sub connect {
|
||||
sub disconnect {
|
||||
my ($self) = @_;
|
||||
|
||||
$self->print_status_timer->Stop;
|
||||
$self->status_timer->Stop;
|
||||
$self->temp_timer->Stop;
|
||||
return if !$self->is_connected;
|
||||
|
||||
$self->printing->printing(0) if $self->printing;
|
||||
$self->printing(undef);
|
||||
$self->{gauge}->Hide;
|
||||
$self->{temp_panel}->Hide;
|
||||
$self->sender->disconnect;
|
||||
$self->set_status("Not connected");
|
||||
$self->set_status("");
|
||||
$self->_update_connection_controls;
|
||||
$self->reload_jobs;
|
||||
}
|
||||
@ -280,8 +365,11 @@ sub print_job {
|
||||
$self->{gauge}->Show;
|
||||
$self->Layout;
|
||||
|
||||
$self->print_status_timer->Start(PRINT_STATUS_TIMER_INTERVAL, wxTIMER_CONTINUOUS);
|
||||
$self->set_status('Printing...');
|
||||
{
|
||||
my @time = localtime(time);
|
||||
$self->{log_textctrl}->AppendText(sprintf "=====\nPrint started at %02d:%02d:%02d\n", @time[2,1,0]);
|
||||
}
|
||||
}
|
||||
|
||||
sub print_completed {
|
||||
@ -294,9 +382,12 @@ sub print_completed {
|
||||
$self->_update_connection_controls;
|
||||
$self->{gauge}->Hide;
|
||||
$self->Layout;
|
||||
$self->print_status_timer->Stop;
|
||||
|
||||
$self->set_status('Print completed.');
|
||||
{
|
||||
my @time = localtime(time);
|
||||
$self->{log_textctrl}->AppendText(sprintf "Print completed at %02d:%02d:%02d\n", @time[2,1,0]);
|
||||
}
|
||||
|
||||
# reorder jobs
|
||||
@{$self->jobs} = sort { $a->printed <=> $b->printed } @{$self->jobs};
|
||||
|
@ -86,6 +86,7 @@ sub _init_tabpanel {
|
||||
|
||||
if (!$self->{no_plater}) {
|
||||
$panel->AddPage($self->{plater} = Slic3r::GUI::Plater->new($panel), "Plater");
|
||||
$panel->AddPage($self->{controller} = Slic3r::GUI::Controller->new($panel), "Controller");
|
||||
}
|
||||
$self->{options_tabs} = {};
|
||||
|
||||
@ -215,22 +216,25 @@ sub _init_menubar {
|
||||
# Window menu
|
||||
my $windowMenu = Wx::Menu->new;
|
||||
{
|
||||
my $tab_count = $self->{no_plater} ? 3 : 4;
|
||||
my $tab_offset = 0;
|
||||
if (!$self->{no_plater}) {
|
||||
$self->_append_menu_item($windowMenu, "Select &Plater Tab\tCtrl+1", 'Show the plater', sub {
|
||||
$self->select_tab(0);
|
||||
}) unless $self->{no_plater};
|
||||
$self->_append_menu_item($windowMenu, "Select P&rint Settings Tab\tCtrl+2", 'Show the print settings', sub {
|
||||
$self->select_tab($tab_count-3);
|
||||
});
|
||||
$self->_append_menu_item($windowMenu, "Select &Filament Settings Tab\tCtrl+3", 'Show the filament settings', sub {
|
||||
$self->select_tab($tab_count-2);
|
||||
});
|
||||
$self->_append_menu_item($windowMenu, "Select Print&er Settings Tab\tCtrl+4", 'Show the printer settings', sub {
|
||||
$self->select_tab($tab_count-1);
|
||||
$self->_append_menu_item($windowMenu, "Select &Controller Tab\tCtrl+T", 'Show the printer controller', sub {
|
||||
$self->select_tab(1);
|
||||
});
|
||||
$windowMenu->AppendSeparator();
|
||||
$self->_append_menu_item($windowMenu, "Printer &Controller\tCtrl+T", 'Show the printer controller', sub {
|
||||
wxTheApp->show_printer_controller;
|
||||
$tab_offset += 2;
|
||||
}
|
||||
$self->_append_menu_item($windowMenu, "Select P&rint Settings Tab\tCtrl+2", 'Show the print settings', sub {
|
||||
$self->select_tab($tab_offset+0);
|
||||
});
|
||||
$self->_append_menu_item($windowMenu, "Select &Filament Settings Tab\tCtrl+3", 'Show the filament settings', sub {
|
||||
$self->select_tab($tab_offset+1);
|
||||
});
|
||||
$self->_append_menu_item($windowMenu, "Select Print&er Settings Tab\tCtrl+4", 'Show the printer settings', sub {
|
||||
$self->select_tab($tab_offset+2);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1078,7 +1078,7 @@ sub on_export_completed {
|
||||
my $do_print = 0;
|
||||
if ($result) {
|
||||
if ($self->{print_file}) {
|
||||
$message = "Adding file to print queue...";
|
||||
$message = "File added to print queue";
|
||||
$do_print = 1;
|
||||
} elsif ($self->{send_gcode_file}) {
|
||||
$message = "Sending G-code file to the OctoPrint server...";
|
||||
@ -1108,7 +1108,7 @@ sub do_print {
|
||||
my $printer_tab = $self->GetFrame->{options_tabs}{printer};
|
||||
my $printer_name = $printer_tab->get_current_preset->name;
|
||||
|
||||
my $controller = wxTheApp->show_printer_controller;
|
||||
my $controller = $self->GetFrame->{controller};
|
||||
my $printer_panel = $controller->add_printer($printer_name, $printer_tab->config);
|
||||
|
||||
my $filament_stats = $self->{print}->filament_stats;
|
||||
@ -1116,10 +1116,7 @@ sub do_print {
|
||||
$filament_stats = { map { $filament_names[$_] => $filament_stats->{$_} } keys %$filament_stats };
|
||||
$printer_panel->load_print_job($self->{print_file}, $filament_stats);
|
||||
|
||||
$controller->Iconize(0); # restore the window if minimized
|
||||
$controller->SetFocus(); # focus on my window
|
||||
$controller->Raise(); # bring window to front
|
||||
$controller->Show(1); # show the window
|
||||
$self->GetFrame->select_tab(1);
|
||||
}
|
||||
|
||||
sub send_gcode {
|
||||
@ -1426,6 +1423,7 @@ sub object_list_changed {
|
||||
|
||||
if ($self->{export_gcode_output_file} || $self->{send_gcode_file}) {
|
||||
$self->{btn_export_gcode}->Disable;
|
||||
$self->{btn_print}->Disable;
|
||||
$self->{btn_send_gcode}->Disable;
|
||||
}
|
||||
|
||||
|
@ -158,6 +158,34 @@ GCodeSender::resume_queue()
|
||||
this->send();
|
||||
}
|
||||
|
||||
// purge log and return its contents
|
||||
std::vector<std::string>
|
||||
GCodeSender::purge_log()
|
||||
{
|
||||
boost::lock_guard<boost::mutex> l(this->log_mutex);
|
||||
std::vector<std::string> retval;
|
||||
retval.reserve(this->log.size());
|
||||
while (!this->log.empty()) {
|
||||
retval.push_back(this->log.front());
|
||||
this->log.pop();
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::string
|
||||
GCodeSender::getT() const
|
||||
{
|
||||
boost::lock_guard<boost::mutex> l(this->log_mutex);
|
||||
return this->T;
|
||||
}
|
||||
|
||||
std::string
|
||||
GCodeSender::getB() const
|
||||
{
|
||||
boost::lock_guard<boost::mutex> l(this->log_mutex);
|
||||
return this->B;
|
||||
}
|
||||
|
||||
void
|
||||
GCodeSender::do_close()
|
||||
{
|
||||
@ -214,8 +242,10 @@ GCodeSender::on_read(const boost::system::error_code& error,
|
||||
}
|
||||
|
||||
// copy the read buffer into string
|
||||
std::string line((std::istreambuf_iterator<char>(&this->read_buffer)),
|
||||
std::istreambuf_iterator<char>());
|
||||
std::istream is(&this->read_buffer);
|
||||
std::string line;
|
||||
std::getline(is, line);
|
||||
// note that line might contain \r at its end
|
||||
|
||||
// parse incoming line
|
||||
if (!this->connected
|
||||
@ -236,10 +266,8 @@ GCodeSender::on_read(const boost::system::error_code& error,
|
||||
} else if (boost::istarts_with(line, "resend") // Marlin uses "Resend: "
|
||||
|| boost::istarts_with(line, "rs")) {
|
||||
// extract the first number from line
|
||||
using boost::lexical_cast;
|
||||
using boost::bad_lexical_cast;
|
||||
boost::algorithm::trim_left_if(line, !boost::algorithm::is_digit());
|
||||
size_t toresend = lexical_cast<size_t>(line.substr(0, line.find_first_not_of("0123456789")));
|
||||
size_t toresend = boost::lexical_cast<size_t>(line.substr(0, line.find_first_not_of("0123456789")));
|
||||
if (toresend == this->sent) {
|
||||
{
|
||||
boost::lock_guard<boost::mutex> l(this->queue_mutex);
|
||||
@ -250,6 +278,28 @@ GCodeSender::on_read(const boost::system::error_code& error,
|
||||
} else {
|
||||
printf("Cannot resend %lu (last was %lu)\n", toresend, this->sent);
|
||||
}
|
||||
} else if (boost::starts_with(line, "wait")) {
|
||||
// ignore
|
||||
} else {
|
||||
// push any other line into the log
|
||||
boost::lock_guard<boost::mutex> l(this->log_mutex);
|
||||
this->log.push(line);
|
||||
}
|
||||
|
||||
// parse temperature info
|
||||
{
|
||||
size_t pos = line.find("T:");
|
||||
if (pos != std::string::npos && line.size() > pos + 2) {
|
||||
// we got temperature info
|
||||
boost::lock_guard<boost::mutex> l(this->log_mutex);
|
||||
this->T = line.substr(pos+2, line.find_first_not_of("0123456789.", pos+2) - (pos+2));
|
||||
|
||||
pos = line.find("B:");
|
||||
if (pos != std::string::npos && line.size() > pos + 2) {
|
||||
// we got bed temperature info
|
||||
this->B = line.substr(pos+2, line.find_first_not_of("0123456789.", pos+2) - (pos+2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->do_read();
|
||||
|
@ -27,6 +27,9 @@ class GCodeSender : private boost::noncopyable {
|
||||
size_t queue_size() const;
|
||||
void pause_queue();
|
||||
void resume_queue();
|
||||
std::vector<std::string> purge_log();
|
||||
std::string getT() const;
|
||||
std::string getB() const;
|
||||
|
||||
private:
|
||||
asio::io_service io;
|
||||
@ -46,6 +49,11 @@ class GCodeSender : private boost::noncopyable {
|
||||
size_t sent;
|
||||
std::string last_sent;
|
||||
|
||||
// this mutex guards log, T, B
|
||||
mutable boost::mutex log_mutex;
|
||||
std::queue<std::string> log;
|
||||
std::string T, B;
|
||||
|
||||
void set_baud_rate(unsigned int baud_rate);
|
||||
void set_error_status(bool e);
|
||||
void do_send(const std::string &line);
|
||||
|
@ -18,6 +18,9 @@
|
||||
void send(std::string s, bool priority = false);
|
||||
void pause_queue();
|
||||
void resume_queue();
|
||||
std::vector<std::string> purge_log();
|
||||
std::string getT();
|
||||
std::string getB();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user