Status Monitor¶
Hazzy uses GObject signaling to inform its widgets of any changes to the status
of linuxcnc. status.py runs in a 50ms loop and 'listens' for any changes in the
linuxcnc.stat
attributes. When a change is detected, status.py emits a GObject
signal with the same name as the attribute that changed, and passes along
the updated value. A python script can connect a callback to these signals, which
can then perform any necessary updates when a signal is received.
This is referred to as event-driven programing, and has several advantages:
-
Instead of having each widget actively polling LinuxCNC for status updates, at (say) 100ms intervals (regardless of whether a change has actually occurred), only one script (status.py) needs to poll for changes. This reduces the load on the LinuxCNC status channel.
-
Widgets can simply connect a callback, wait for a signal to be received, and then update only what is necessary. This greatly reduces the load on the system by avoiding useless screen refreshes, etc.
Note
status.py monitors only the linuxcnc.stat
attributes which have been
connected to a callback. This is to avoid needless monitoring of attributes,
and emission of signals which are not used.
Connecting Callbacks¶
status.on_changed(attribute, callback)
where attribute is any linuxcnc.stat attribute and callback is the method to be called when the value of that attribute changes.
Examples¶
Here is a basic example that prints the tool number when the
linuxcnc.stat.tool_in_spindle
attribute changes.
1 2 3 4 5 6 7 8 9 | #!/usr/bin/env python from hazzy.utilities import status def update_tool(status, tool_num): print tool_num # Connect "tool_in_spindle" changed signal to "update_tool" callback status.on_changed('stat.tool_in_spindle', update_tool) |
status.py also monitors the linuxcnc.stat.joint
dictionaries for changes. So
it is simple to do things like keep track of the homing status, report the current
following error, etc.
Here is an example of printing the following error for each joint used in the machine
1 2 3 4 5 | def print_ferror(status, joint_num, ferror): print 'joint {} f-error: {:.5f}'.format(joint_num, ferror) # Connect "joint.ferror_current" changed signal to "print_ferror" callback status.on_changed('joint.ferror_current', print_ferror) |
Note
This is roughly equivalent to the pseudo code
1 2 3 4 5 6 7 8 | while True: stat.poll() for jnum in range(num_joints): if ferror has changed: print stat.joint[jnum]['ferror_current'] sleep(.05) |
So the signal will only be emitted if the value has changed since the previous emission. If no joints are moving no signal will be emitted. If one joint is moving, only the ferror for that joint will be emitted, etc.
Additional Signals¶
In addition to the linuxcnc.stat attributes, status.py also has five convenience signals.
axis-positions¶
The axis-position signal is emitted every cycle and returns a tuple of three tuples of floats representing:
-
Current absolute axis positions in machine units, taking into account the setting of
[DISPLAY] POSITION_FEEDBACK
in the INI -
Current g5x relative position in machine units, taking into account any active g92 offsets, rotation in the XY plane, and/or tool offsets
-
Remaining distance of the current move, as reported by the trajectory planner
Note
Only the position values for used axes are calculated, the positions of all
unused axes will be reported as 0. Status.py uses the the value of
linuxcnc.axis_mask do determine which axes are in use. This should reflect
the axes as defined by [TRAJ] COORDINATES
in the INI.
joint-positions¶
The joint-positions signal is emitted every cycle and returns a tuple of floats representing:
- Current absolute joint positions in machine units, taking into account the
setting of
[DISPLAY] POSITION_FEEDBACK
in the INI
formated-gcodes¶
The formated-gcodes signal returns a list containing the currently active g-codes formed as strings.
Example:
1 2 3 4 | def update_gcodes(widget, gcodes): print "G-codes: ", " ".join(gcodes) status.on_changed('formated_gcodes', update_gcodes) |
Result: G-codes: G8 G17 G20 G40 G49 G54 G64 G80 G90 G91.1 G94 G97 G99
formated-mcodes¶
The formated-mcodes signal returns a list containing the currently active m-codes formed as strings.
Example:
1 2 3 4 | def update_mcodes(widget, mcodes): print "M-codes: ", " ".join(mcodes) status.on_changed('formated_mcodes', update_mcodes) |
Result: M-codes: M0 M5 M9 M48 M53
file-loaded¶
The file-loaded signal is emitted when a file is loaded and returns the full path to the file. This makes an attempt to avoid spurious emissions resulting from remap procedures.