Solved inter-thread communication issues by feeding commands over a queue.
This commit is contained in:
@@ -49,15 +49,15 @@ using namespace nanogui;
|
||||
|
||||
grbl::machine cnc{};
|
||||
|
||||
class SenderApp : public Screen, public grbl::machine_listener {
|
||||
class SenderApp : public Screen {
|
||||
public:
|
||||
|
||||
Window *window;
|
||||
grbl::jog_state jog;
|
||||
TextBox *txt_status;
|
||||
TextBox *txtMessage;
|
||||
TextBox *txt_message;
|
||||
nanogui::Color color_red = nanogui::Color(255, 0, 0, 255);
|
||||
nanogui::Color colGreen = nanogui::Color(0, 255, 0, 255);
|
||||
nanogui::Color color_green = nanogui::Color(0, 255, 0, 255);
|
||||
int last_alarm = 0;
|
||||
grbl::program pgm;
|
||||
Button *btn_load_program, *btn_check_program, *btn_run_program;
|
||||
@@ -242,8 +242,8 @@ public:
|
||||
//
|
||||
status_text_holder->add<Label>("");
|
||||
|
||||
txtMessage = status_text_holder->add<TextBox>("");
|
||||
txtMessage->set_fixed_width(300);
|
||||
txt_message = status_text_holder->add<TextBox>("");
|
||||
txt_message->set_fixed_width(300);
|
||||
|
||||
status_text_holder->add<Label>("");
|
||||
|
||||
@@ -806,58 +806,8 @@ public:
|
||||
return Screen::resize_event(size);
|
||||
}
|
||||
|
||||
void on_connected() override {
|
||||
}
|
||||
|
||||
void on_disconnected() override {
|
||||
}
|
||||
|
||||
void on_settings_reloaded() override {
|
||||
}
|
||||
|
||||
void on_parameters_reloaded() override {
|
||||
refresh_offset();
|
||||
update_dro();
|
||||
}
|
||||
|
||||
|
||||
grbl::realtime_status_report last_report;
|
||||
|
||||
volatile bool machine_initialized = false;
|
||||
|
||||
void on_init_completed() override {
|
||||
machine_initialized = true;
|
||||
// need to do UI related things in UI thread
|
||||
}
|
||||
|
||||
void on_realtime_status_report(grbl::realtime_status_report report) override {
|
||||
// if (report == last_report) return;
|
||||
|
||||
// if (last_report.status != report.status) {
|
||||
txt_status->set_value(grbl::status_to_string(cnc.get_status().status));
|
||||
|
||||
if (cnc.get_status().status == grbl::machine_status::alarm) {
|
||||
txt_status->set_tooltip(grbl::alarm_to_string(last_alarm));
|
||||
} else {
|
||||
txt_status->set_tooltip(cnc.get_status().sub_status);
|
||||
}
|
||||
// }
|
||||
|
||||
|
||||
// FIXME: ugly way of retrieving the bg color
|
||||
btn_pin_door->set_background_color(report.signals.bit.door ? color_red : btn_load_program->background_color());
|
||||
btn_pin_hold->set_background_color(report.signals.bit.hold ? color_red : btn_load_program->background_color());
|
||||
btn_pin_reset->set_background_color(report.signals.bit.soft_reset ? color_red : btn_load_program->background_color());
|
||||
btn_pin_cycle_start->set_background_color(report.signals.bit.cycle_start ? color_red : btn_load_program->background_color());
|
||||
btn_pin_limit_x->set_background_color(report.signals.bit.x_limit ? color_red : btn_load_program->background_color());
|
||||
btn_pin_limit_y->set_background_color(report.signals.bit.y_limit ? color_red : btn_load_program->background_color());
|
||||
btn_pin_limit_z->set_background_color(report.signals.bit.z_limit ? color_red : btn_load_program->background_color());
|
||||
btn_pin_probe->set_background_color(report.signals.bit.probe ? color_red : btn_load_program->background_color());
|
||||
|
||||
update_dro();
|
||||
last_report = report;
|
||||
}
|
||||
|
||||
void update_dro() {
|
||||
auto work_pos = cnc.get_work_pos();
|
||||
|
||||
@@ -874,63 +824,6 @@ public:
|
||||
mpos_z_text->set_value(dro_ss.str());
|
||||
}
|
||||
|
||||
void on_banner(std::string line) override {
|
||||
}
|
||||
|
||||
void on_message(std::string message) override {
|
||||
txtMessage->set_value(message);
|
||||
set_caption(message);
|
||||
}
|
||||
|
||||
void on_alarm(int alarm) override {
|
||||
last_alarm = alarm;
|
||||
}
|
||||
|
||||
void on_probe_result(bool probe_touched, float *probe_coords) override {
|
||||
std::stringstream ss;
|
||||
ss << "Probing ended. Result: " << std::boolalpha << probe_touched << " at coords: ";
|
||||
for (auto i = 0; i < 3; i++) {
|
||||
ss << probe_coords[i] << ", ";
|
||||
}
|
||||
new MessageDialog(this, MessageDialog::Type::Warning, "Probe result", ss.str());
|
||||
}
|
||||
|
||||
volatile bool should_render_grid = false;
|
||||
void on_heightmap_probe_acquired(grbl::heightmap *grid) override {
|
||||
std::cout << "Updating grid" << std::endl;
|
||||
// let's try to update this from the UI thread since the call is invoked from the
|
||||
// grbl communicator thread.
|
||||
should_render_grid = true;
|
||||
}
|
||||
|
||||
void on_check_completed(bool success, size_t failed_index, size_t error) override {
|
||||
btn_check_program->set_background_color(success ? colGreen : color_red);
|
||||
if (success) {
|
||||
btn_run_program->set_enabled(true);
|
||||
new MessageDialog(this, MessageDialog::Type::Information, "Check result", "Program checked successfully");
|
||||
} else {
|
||||
btn_run_program->set_enabled(false);
|
||||
std::stringstream ss;
|
||||
auto i = pgm.instruction_at(failed_index);
|
||||
ss << "Program check failed at line " << i.line << " (" << i.command << "). Error: " << error << ", "
|
||||
<< grbl::error_to_string(error);
|
||||
new MessageDialog(this, MessageDialog::Type::Warning, "Check result", ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
void on_run_completed(bool success, size_t failed_index, size_t error) override {
|
||||
btn_run_program->set_background_color(success ? colGreen : color_red);
|
||||
if (success) {
|
||||
new MessageDialog(this, MessageDialog::Type::Information, "Run result", "Program executed successfully");
|
||||
} else {
|
||||
std::stringstream ss;
|
||||
auto i = pgm.instruction_at(failed_index);
|
||||
ss << "Program execution failed at line " << i.line << " (" << i.command << "). Error: " << error << ", "
|
||||
<< grbl::error_to_string(error);
|
||||
new MessageDialog(this, MessageDialog::Type::Warning, "Run result", ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool keyboard_event(int key, int scancode, int action, int modifiers) override {
|
||||
if (Screen::keyboard_event(key, scancode, action, modifiers))
|
||||
@@ -1056,23 +949,125 @@ public:
|
||||
}
|
||||
|
||||
void draw(NVGcontext *ctx) override {
|
||||
// not pretty but need to do this in UI thread
|
||||
if (machine_initialized) {
|
||||
fill_in_settings();
|
||||
fill_in_parameters();
|
||||
std::shared_ptr<grbl::machine_event> event;
|
||||
while ((event = cnc.pop_event()) != nullptr) {
|
||||
switch (event->type) {
|
||||
case grbl::machine_event_type::connected:
|
||||
break;
|
||||
case grbl::machine_event_type::disconnected:
|
||||
break;
|
||||
case grbl::machine_event_type::report_received: {
|
||||
|
||||
perform_layout();
|
||||
auto ev = dynamic_cast<grbl::machine_event_report_received *>(event.get());
|
||||
|
||||
refresh_offset();
|
||||
update_dro();
|
||||
machine_initialized = false;
|
||||
txt_status->set_value(grbl::status_to_string(cnc.get_status().status));
|
||||
|
||||
if (cnc.get_status().status == grbl::machine_status::alarm) {
|
||||
txt_status->set_tooltip(grbl::alarm_to_string(last_alarm));
|
||||
} else {
|
||||
txt_status->set_tooltip(cnc.get_status().sub_status);
|
||||
}
|
||||
|
||||
// FIXME: ugly way of retrieving the bg color
|
||||
btn_pin_door->set_background_color(ev->report.signals.bit.door ? color_red : btn_load_program->background_color());
|
||||
btn_pin_hold->set_background_color(ev->report.signals.bit.hold ? color_red : btn_load_program->background_color());
|
||||
btn_pin_reset->set_background_color(
|
||||
ev->report.signals.bit.soft_reset ? color_red : btn_load_program->background_color());
|
||||
btn_pin_cycle_start->set_background_color(
|
||||
ev->report.signals.bit.cycle_start ? color_red : btn_load_program->background_color());
|
||||
btn_pin_limit_x->set_background_color(
|
||||
ev->report.signals.bit.x_limit ? color_red : btn_load_program->background_color());
|
||||
btn_pin_limit_y->set_background_color(
|
||||
ev->report.signals.bit.y_limit ? color_red : btn_load_program->background_color());
|
||||
btn_pin_limit_z->set_background_color(
|
||||
ev->report.signals.bit.z_limit ? color_red : btn_load_program->background_color());
|
||||
btn_pin_probe->set_background_color(ev->report.signals.bit.probe ? color_red : btn_load_program->background_color());
|
||||
|
||||
update_dro();
|
||||
last_report = ev->report;
|
||||
break;
|
||||
}
|
||||
case grbl::machine_event_type::banner:
|
||||
break;
|
||||
case grbl::machine_event_type::message: {
|
||||
auto ev = dynamic_cast<grbl::machine_event_message *>(event.get());
|
||||
txt_message->set_value(ev->message);
|
||||
set_caption(ev->message);
|
||||
break;
|
||||
}
|
||||
case grbl::machine_event_type::alarm: {
|
||||
auto ev = dynamic_cast<grbl::machine_event_alarm *>(event.get());
|
||||
last_alarm = ev->alarm;
|
||||
break;
|
||||
}
|
||||
case grbl::machine_event_type::init_completed:
|
||||
fill_in_settings();
|
||||
fill_in_parameters();
|
||||
|
||||
perform_layout();
|
||||
|
||||
refresh_offset();
|
||||
update_dro();
|
||||
break;
|
||||
case grbl::machine_event_type::run_completed: {
|
||||
auto ev = dynamic_cast<grbl::machine_event_run_completed *>(event.get());
|
||||
btn_run_program->set_background_color(ev->success ? color_green : color_red);
|
||||
if (ev->success) {
|
||||
new MessageDialog(this, MessageDialog::Type::Information, "Run result", "Program executed successfully");
|
||||
} else {
|
||||
std::stringstream ss;
|
||||
auto i = pgm.instruction_at(ev->failed_index);
|
||||
ss << "Program execution failed at line " << i.line << " (" << i.command << "). Error: "
|
||||
<< ev->error << ", "
|
||||
<< grbl::error_to_string(ev->error);
|
||||
new MessageDialog(this, MessageDialog::Type::Warning, "Run result", ss.str());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case grbl::machine_event_type::check_completed: {
|
||||
auto ev = dynamic_cast<grbl::machine_event_check_completed *>(event.get());
|
||||
|
||||
btn_check_program->set_background_color(ev->success ? color_green : color_red);
|
||||
if (ev->success) {
|
||||
btn_run_program->set_enabled(true);
|
||||
new MessageDialog(this, MessageDialog::Type::Information, "Check result", "Program checked successfully");
|
||||
} else {
|
||||
btn_run_program->set_enabled(false);
|
||||
std::stringstream ss;
|
||||
auto i = pgm.instruction_at(ev->failed_index);
|
||||
ss << "Program check failed at line " << i.line << " (" << i.command << "). Error: "
|
||||
<< ev->error << ", "
|
||||
<< grbl::error_to_string(ev->error);
|
||||
new MessageDialog(this, MessageDialog::Type::Warning, "Check result", ss.str());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case grbl::machine_event_type::settings_reloaded:
|
||||
break;
|
||||
case grbl::machine_event_type::parameters_reloaded:
|
||||
refresh_offset();
|
||||
update_dro();
|
||||
break;
|
||||
case grbl::machine_event_type::probe_result: {
|
||||
auto ev = dynamic_cast<grbl::machine_event_probe_result *>(event.get());
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Probing ended. Result: " << std::boolalpha << ev->probe_touched << " at coords: ";
|
||||
for (float probe_coord: ev->probe_coords) {
|
||||
ss << probe_coord << ", ";
|
||||
}
|
||||
new MessageDialog(this, MessageDialog::Type::Warning, "Probe result", ss.str());
|
||||
break;
|
||||
}
|
||||
case grbl::machine_event_type::heightmap_probe_acquired: {
|
||||
std::cout << "Updating grid" << std::endl;
|
||||
auto ev = dynamic_cast<grbl::machine_event_heightmap_probe_acquired *>(event.get());
|
||||
renderer.update_grid(*ev->grid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: change this to something prettier. make a pipe/queue for in-between threads comm
|
||||
if (should_render_grid) {
|
||||
renderer.update_grid(heightmap_grid);
|
||||
should_render_grid = false;
|
||||
}
|
||||
|
||||
Widget::draw(ctx);
|
||||
}
|
||||
@@ -1131,7 +1126,6 @@ int main(int argc, char **argv) {
|
||||
app->draw_all();
|
||||
app->set_visible(true);
|
||||
|
||||
cnc.set_listener(app);
|
||||
cnc.connect();
|
||||
|
||||
nanogui::mainloop(1 / 60.f * 1000);
|
||||
|
||||
Reference in New Issue
Block a user