Testing Periodic for Errors
Add a Test Button
-
Open up gui4.glade and click on the button bar then pick the editor. In the Hierarchy tab add a button. Change the Name: to test_error then press the enter key or it might not take then change Stock Id: to Error then close the Tool Bar Editor.
Your project should look like this now.
-
Click on the new button and check that the Name: is correct then on the Signals tab add the on_test_error_clicked handler to the GtkToolButton clicked signal and don’t forget to press enter so it will save.
Your project should look like this now.
The Python
-
Open up gui4.py and add this function to our code. We have an intentional typo in the code. If this code is run in the periodic function we would not get any error reported to the terminal and periodic would just quit. This way we can test for errors in our code before adding them to the periodic function.
def on_test_error_clicked(self, widget, data=None): self.status.poll() data = self.status.actual_position[2] text = "% 9.4f"% (data) self.builder.get_object("dro_zz").set_text(text)
#!/usr/bin/env python import gtk import gobject import gladevcp.makepins from gladevcp.gladebuilder import GladeBuilder import hal import sys,os # set up paths to files BASE = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "..")) libdir = os.path.join(BASE, "lib", "python") sys.path.insert(0, libdir) datadir = os.path.join(BASE, "share", "linuxcnc") xmlname = os.path.join(datadir,"gui4.glade") import linuxcnc class gui3(object): def __init__(self): self.emc = linuxcnc self.error_channel = self.emc.error_channel() self.status = self.emc.stat() self.builder = gtk.Builder() self.builder.add_from_file(xmlname) self.halcomp = hal.component("gui4") self.builder.connect_signals(self) self.window = self.builder.get_object("window1") self.statusbar = self.builder.get_object("statusbar1") self.window.show() self.panel = gladevcp.makepins.GladePanel(self.halcomp, xmlname, self.builder, None) self.halcomp.ready() # since the main loop is needed to handle the UI and its events, blocking calls like sleep() # will block the UI as well, so everything goes through event handlers (aka callbacks) # The gobject.timeout_add() function sets a function to be called at regular intervals # the time between calls to the function, in milliseconds gobject.timeout_add(100, self.periodic) # time between calls to the function, in milliseconds self.machine_status = 0 def periodic(self): # fetch status items and update screen # poll the error channel self.error_status = self.error_channel.poll() if self.error_status: self.error_kind, self.error_text = self.error_status if self.error_kind in (linuxcnc.NML_ERROR, linuxcnc.OPERATOR_ERROR): self.error_type = "Error " else: self.error_type = "Info " self.message_id = self.statusbar.push(0, self.error_type + self.error_text) # poll the status channel self.status.poll() data = self.status.actual_position[0] text = "% 9.4f"% (data) self.builder.get_object("dro_x").set_text(text) data = self.status.actual_position[1] text = "% 9.4f"% (data) self.builder.get_object("dro_y").set_text(text) data = self.status.actual_position[2] text = "% 9.4f"% (data) self.builder.get_object("dro_z").set_text(text) return True # must return True to keep running def on_hal_stat1_mode_mdi(self, widget, data=None): self.mode_mdi = 1 def on_test_error_clicked(self, widget, data=None): self.status.poll() data = self.status.actual_position[2] text = "% 9.4f"% (data) self.builder.get_object("dro_zz").set_text(text) def on_window1_destroy(self, widget, data=None): print "quit with cancel" gtk.main_quit() def on_gtk_quit_activate(self, menuitem, data=None): print "quit from menu" gtk.main_quit() if __name__ == "__main__": app = gui3() gtk.main()
Testing the Code
-
Copy the changed files like before with:
sudo cp gui4 /usr/bin sudo cp gui4.glade /usr/share/linuxcnc
-
Now run the GUI using the desktop launcher and your project should look like this now.
Now when you press the error button you should see the error in the terminal. Because the builder could not find the object named dro_zz it could not set the text so you get the cryptic message about NoneType.
To see the results of having an error in the periodic function change an object name, copy the changed python file to the installed location then run the configuration again and run a file and notice that nothing gets updated in the DRO tab because the periodic function had an error and has quit cycling.
Using the above process of editing and copying the files to the installed location as you build your GUI will be about the easiest way to test it as you build it.