1. Intro

GStat is a python class used to send messages from linuxcnc to other python programs.
It uses GObject to deliver messages, making it easy to listen for specific information.
This is referred to as event-driven programming, which is more efficient then every program
polling linuxcnc at the same time.
GladeVCP, Gscreen, Gmoccapy and QtVCP use GStat extensively.
GStat is in the hal_glib module

2. Overview

First a program imports the hal_glib module and instantiates GStat.
Then it connects to the messages it wishes to monitor.
GStat checks linuxcnc’s status every 100ms and if there are differences from
the last check, it will send a callback message to all the connected programs
with the current status.
When GStat calls the registered function, it sends the GStat object plus any return codes from the message.
typical code signatures:

GSTAT.connect('MESSGAE-TO-LISTEN-FOR', FUNCTION_TO_CALL)

def FUNCTION_TO_CALL(gstat_object, return_codes):

Often LAMBDA is used to strip the GSTAT object and manipulate the return codes):

GSTAT.connect('MESSGAE-TO-LISTEN-FOR', lambda o, return: FUNCTION_TO_CALL(not return))

def FUNCTION_TO_CALL(return_codes):

3. Sample GStat Code

There are some basic patterns for using GStat, depending on what library
You are using them in.
If using GStat with Gladevcp, Gscreen, or Qtvcp, the gobject library is not needed,
Those toolkits already set up Gobject.

3.1. Sample HAL component code pattern

This program creates two HAL pins that output the status
of G20/G21.

#!/usr/bin/env python

import hal
from hal_glib import GStat
import gobject
GSTAT = GStat()

# callback to change HAL pin state
def mode_changed(obj, data):
        h['g20'] = not data
        h['g21'] = data

# Make a component and pins
h = hal.component("metric_status")
h.newpin("g20", hal.HAL_BIT, hal.HAL_OUT)
h.newpin("g21", hal.HAL_BIT, hal.HAL_OUT)
h.ready()

# connect a GSTAT message to a callback function
GSTAT.connect("metric-mode-changed",mode_changed)

# force GSTAT to initialize states
GSTAT.forced_update()

# loop till exit
try:
        gobject.MainLoop().run()
except KeyboardInterrupt:
    raise SystemExit

This would be loaded with loadusr python PATH-TO-FILE/FILENAME.py
or if you need to wait for the pins to be made before continuing:
loadusr python -Wn metric_status PATH-TO-FILE/FILENAME.py
The pins would be: metric_status.g20 and metric_status.g21

3.2. GladeVCP python extension code pattern

This file assumes there are three GTK labels named:
state_label
e_state_label
interp_state_label

#!/usr/bin/env python

from hal_glib import GStat
GSTAT = GStat()

class HandlerClass:

    def __init__(self, halcomp, builder, useropts):
        self.builder = builder

        GSTAT.connect("state-estop",lambda w: self.update_estate_label('ESTOP'))
        GSTAT.connect("state-estop-reset",lambda w: self.update_estate_label('RESET'))

        GSTAT.connect("state-on",lambda w: self.update_state_label('MACHIBE ON'))
        GSTAT.connect("state-off",lambda w: self.update_state_label('MACHINE OFF'))

        GSTAT.connect("interp-paused",lambda w: self.update_interp_label('Paused'))
        GSTAT.connect("interp-run",lambda w: self.update_interp_label('Run'))
        GSTAT.connect("interp-idle",lambda w: self.update_interp_label('Idle'))

    def update_state_label(self,text):
        self.builder.get_object('state_label').set_label("State: %s" % (text))

    def update_estate_label(self,text):
        self.builder.get_object('e_state_label').set_label("E State: %s" % (text))

    def update_interp_label(self,text):
        self.builder.get_object('interp_state_label').set_label("Interpeter State: %s" % (text))

def get_handlers(halcomp,builder,useropts):
    return [HandlerClass(halcomp,builder,useropts)]

3.3. QTVCP python extension code pattern

Qtvcp extends GStat, so must be loaded differently but all the messages are available in Qtvcp.
This handler file assumes there are three QLabels named:
state_label
e_state_label
interp_state_label

#!/usr/bin/env python

from qtvcp.core import Status
GSTAT = Status()

class HandlerClass:

    def __init__(self, halcomp,widgets,paths):
        self.w = widgets

        GSTAT.connect("state-estop",lambda w: self.update_estate_label('ESTOP'))
        GSTAT.connect("state-estop-reset",lambda w: self.update_estate_label('RESET'))

        GSTAT.connect("state-on",lambda w: self.update_state_label('MACHIBE ON'))
        GSTAT.connect("state-off",lambda w: self.update_state_label('MACHINE OFF'))

        GSTAT.connect("interp-paused",lambda w: self.update_interp_label('Paused'))
        GSTAT.connect("interp-run",lambda w: self.update_interp_label('Run'))
        GSTAT.connect("interp-idle",lambda w: self.update_interp_label('Idle'))

    def update_state_label(self,text):
        self.w.state_label.setText("State: %s" % (text))

    def update_estate_label(self,text):
        self.w.e_state_label.setText("E State: %s" % (text))

    def update_interp_label(self,text):
        self.winterp_state_label.setText("Interpeter State: %s" % (text))

def get_handlers(halcomp,builder,useropts):
    return [HandlerClass(halcomp,widgets,paths)]

4. Messages

periodic

(returns nothing) - sent every 100 ms.

state-estop

(returns nothing) - Sent when linuxcnc is goes into estop.

state-estop-reset

(returns nothing) - Sent when linuxcnc comes out of estop.

state-on

(returns nothing) - Sent when linuxcnc is in machine on state.

state-off

(returns nothing) - Sent when linuxcnc is in machine off state.

homed

(returns string) - Sent as each joint is homed.

all-homed

(returns nothing) - Sent when all defined joints are homed.

not-all-homed

(returns string) - Sends a list of joints not currently homed.

override_limits_changed

(returns string) - Sent if linuxcnc has been directed to override it’s limits.

hard-limits-tripped

(returns bool, Python List) - Sent when any hard limit is tripped. bool indicates if any limit is tripped, the list shows all available joint’s current limit values.

mode-manual

(returns nothing) - Sent when linuxcnc switches to manual mode.

mode-mdi

(returns nothing) - Sent when linuxcnc switches to mdi mode.

mode-auto

(returns nothing) - Sent when linuxcnc switches to auto mode.

command-running

(returns nothing) - Sent when running a program or MDI

command-stopped

(returns nothing) - Sent when a program or MDI stopped

command-error

(returns nothing) - Sent when there is a command error

interp-run

(returns nothing) - Sent when linuxcnc’s interpreter is running an MDI or program.

interp-idle

(returns nothing) - Sent when linuxcnc’s interpreter idle.

interp-paused

(returns nothing) - Sent when linuxcnc’s interpreter is paused.

interp-reading

(returns nothing) - Sent when linuxcnc’s interpreter is reading.

interp-waiting

(returns nothing) - Sent when linuxcnc’s interpreter is waiting.

jograte-changed

(returns float) - Sent when jog rate has changed.
Linuxcnc does not have an internal jog rate.
This is GStat’s internal jog rate.
It is expected to be in the machine’s native units regardless of the current unit mode .

jograte-angular-changed

(returns float) - Sent when the angular jog rate has changed.
Linuxcnc does not have an internal angular jog rate.
This is GStat’s internal jog rate.
It is expected to be in the machine’s native units regardless of the current unit mode .

jogincrement-changed

(returns float) - Sent when jog increment has changed.
Linuxcnc does not have an internal jog increment.
This is GStat’s internal jog increment.
It is expected to be in the machine’s native units regardless of the current unit mode .

jogincrement-angular-changed

(returns float) - Sent when angular jog increment has changed.
Linuxcnc does not have an internal angular jog increment.
This is GStat’s internal angular jog increment.
It is expected to be in the machine’s native units regardless of the current unit mode .

program-pause-changed

(returns bool) - Sent when program is paused/unpaused.

optional-stop-changed

(returns bool) - Sent when optional stop is set/unset

block-delete-changed

(returns bool) - sent when block delete is set/unset.

file-loaded

(returns string) - Sent when linuxcnc has loaded a file

reload-display

(returns nothing) - Sent when there is a request to reload the display

line-changed

(returns integer) - Sent when linuxcnc has read a new line.
Linuxcnc does not update this for every type of line.

tool-in-spindle-changed

(returns integer) - Sent when the tool has changed.

tool-info-changed

(returns python object) - Sent when current tool info changes.

current-tool-offset

(returns python object) - Sent when the current tool offsets change.

motion-mode-changed

(returns integer) - Sent when motion’s mode has changed

spindle-control-changed

(returns bool, integer) - Sent when spindle direction or running status changes.

current-feed-rate

(returns float) - Sent when the current feed rate changes.

current-x-rel-position

(returns float) - Sent every 100ms.

current-position

(returns pyobject, pyobject, pyobject, pyobject) - Sent every 100ms.
returns tuples of position, relative position, distance-to-go and
the joint actual position. Before homing, on multi-joint axes, only joint
position is valid.

current-z-rotation

(returns float) - Sent as the current rotatated angle around the Z axis changes

requested-spindle-speed-changed

(returns float) - Sent when the current requested RPM changes

actual-spindle-speed-changed

(returns float) - Sent when the actual RPM changes based on the HAL pin spindle.0.speed-in.

spindle-override-changed

(returns float) - Sent when the spindle override value changes
in percent

feed-override-changed

(returns float) - Sent when the feed override value changes
in percent

rapid-override-changed

(returns float) - Sent when the rapid override value changes
in percent 0-100

max-velocity-override-changed

(returns float) - Sent when the maximum velocity override value changes
in units per minute

feed-hold-enabled-changed

(returns bool) - Sent when feed hold status changes

itime-mode

(returns bool) - Sent when G93 status changes
(inverse time mode)

fpm-mode

(returns bool) - Sent when G94 status changes
(feed per minute mode)

fpr-mode

(returns bool) - Sent when G95 status changes
(feed per revolution mode)

css-mode

(returns bool) - Sent when G96 status changes
(constant surface feed mode)

rpm-mode

(returns bool) - Sent when G97 status changes
(constatnt RPM mode)

radius-mode

(returns bool) - Sent when G8 status changes
display X in radius mode

diameter-mode

(returns bool) - Sent when G7 status changes
display X in Diameter mode

flood-changed

(returns bool) - Sent when flood coolant state changes.

mist-changed

(returns bool ) - Sent when mist coolant state changes.

m-code-changed

(returns string) - Sent when active M codes change

g-code-changed

(returns string) - Sent when active G code change

metric-mode-changed

(returns bool) - Sent when G21 status changes

user-system-changed

(returns string) - Sent when the reference coordinate system (G5x) changes

mdi-line-selected

(returns string, string) - intended to be sent when an MDI line is selected by user.
This depends on the widget/libraries used.

gcode-line-selected

(returns integer) - intended to be sent when a gcode line is selected by user.
This depends on the widget/libraries used.

graphics-line-selected

(returns integer) - intended to be sent when graphics line is selected by user.
This depends on the widget/libraries used.

graphics-gcode-error

(returns string) - intended to be sent when a gcode error is found when loading.
This depends on the widget/libraries used.

graphics-gcode-properties

(returns string) - intended to be sent when gcode is loaded.
This depends on the widget/libraries used.

graphics-view-changed

(returns string, python Dict or None) - intended to be sent when graphics view is changed.
This depends on the widget/libraries used.

mdi-history-changed

(returns None) - intended to be sent when an MDI history needs to be reloaded.
This depends on the widget/libraries used.

machine-log-changed

(returns None) - intended to be sent when machine log has changed.
This depends on the widget/libraries used.

update-machine-log

(returns string, string) - intended to be sent when updating the machine.
This depends on the widget/libraries used.

move-text-lineup

(returns None) - intended to be sent when moving the cursor one line up in gcode display.
This depends on the widget/libraries used.

move-text-linedown

(returns None) - intended to be sent when moving the cursor one line down in gcode display.
This depends on the widget/libraries used.

dialog-request

(returns python dict) - intended to be sent when requesting a gui dialog.
It uses a python dict for communication.
The dict must include the following keyname pair:

  • NAME: requested dialog name
    The dict usually has more keyname pair - it depends on the dialog.
    dialogs return information using a general message
    This depends on the widget/libraries used.

focus-overlay-changed

(returns bool, string, python object) - intended to be sent when requesting an overlay to be put over the display.
This depends on the widget/libraries used.

play-sound

(returns string) - intended to be sent when requesting a specific sound file to be played.
This depends on the widget/libraries used.

virtual-keyboard

(returns string) - intended to be sent when requesting a on screen keyboard.
This depends on the widget/libraries used.

dro-reference-change-request

(returns integer) - intended to be sent when requesting a DRO widget to change it’s reference.
0 = machine, 1 = relative, 3 = distance-to-go
This depends on the widget/libraries used.

show-preferences

(returns None) - intended to be sent when requesting the screen preferences to be displayed.
This depends on the widget/libraries used.

shutdown

(returns None) - intended to be sent when requesting linuxcnc to shutdown.
This depends on the widget/libraries used.

error

(returns integer, string) - intended to be sent when an error has been reported .
integer represents the kind of error. ERROR, TEXT or DISPLAY
string is the actual error message.
This depends on the widget/libraries used.

general

(returns python dict) - intended to be sent when message must be sent that is not covered by a more specific message.
General message should be used a sparsely as reasonable because all object connected to it will have to parse it.
It uses a python dict for communication.
The dict should include and be checked for a unique id keyname pair:

  • ID: UNIQUE_ID_CODE
    The dict usually has more keyname pair - it depends on implementation.

forced-update

(returns None) - intended to be sent when one wishes to initialize or arbitrarily update an object.
This depends on the widget/libraries used.

5. Functions

These are convenience functions that are commonly used in programming

set_jograte

(float) - Linuxcnc has no internal concept of jog rate -each GUI has it’s own.
This is not always convenient.
This function allows one to set a jog rate for all objects connected to the
signal jograte-changed.
It defaults to 15
GSTAT.set_jog_rate(10) would set the jog rate to 10 machine-units-per-minute and emit the jograte-changed signal.

get_jograte()

(Nothing) - x = GSTAT.get_jograte would return GSTAT’s current internal jograte.

set_jograte_angular

(float) -

get_jograte_angular

(None) -

set_jog_increment_angular

(float, string) -

get_jog_increment_angular

(None) -

set_jog_increments

(float, string) -

get_jog_increments

(None) -

is_all_homed

(nothing) - This will return the current state of all_homed (BOOL).

machine_is_on

(nothing) - This will return the current state of machine (BOOL).

estop_is_clear

(nothing) - This will return the state of Estop (BOOL)

set_tool_touchoff

(tool,axis,value) - This command will record the current mode, switch to MDI mode,
invoke the MDI command: G10 L10 P[TOOL] [AXIS] [VALUE]
wait for it to complete
invoke G43
wait for it to complete
switch back to the original mode.

set_axis_origin

(axis,value) - This command will record the current mode, switch to MDI mode,
invoke the MDI command: G10 L20 P0 [AXIS] [VALUE]
wait for it to complete
switch back to the original mode.
emit a reload-display signal.

do_jog

(axis_number,direction, distance) - This will jog an axis continuously or at a set distance.
You must be in the proper mode to jog.

check_for_modes

(mode) - This function checks for required linuxcnc mode.
It returns a python tuple (state, mode)
mode will be set the mode the system is in
state will set to:
false if mode is 0
false if machine is busy
true if linuxcnc is in the requested mode
None if possible to change, but not in requested mode

get_current_mode

(nothing) - returns integer: the current linuxcnc mode.

set_selected_joint

(integer) - records the selected joint number internally.
requests the joint to be selected by emitting the
joint-selection-changed message.

get_selected_joint

(None) - returns integer representing the internal selected joint number.

set_selected_axis

(string) - records the selected axis letter internally.
requests the axis to be selected by emitting the
axis-selection-changed message.

get_selected_axis

(None) - returns string representing the internal selected axis letter.

is_man_mode

(None) -

is_mdi_mode

(None) -

is_auto_mode

(None) -

is_on_and_idle

(None) -

is_auto_running

(None) -

is_auto_paused

(None) -

is_file_loaded

(None) -

is_metric_mode

(None) -

is_spindle_on

(None) -

shutdown

(None) -

6. Known Issues

Some status points are reported wrongly during a running program.
This is because the interpreter runs ahead of the current position of a running program.
This will hopefully be resolved with the merge of state-tags branch.