GStat.txt
1 [[cha:GStat]] 2 3 = GStat 4 5 == Intro 6 7 GStat is a python class used to send messages from linuxcnc to other python programs. + 8 It uses GObject to deliver messages, making it easy to listen for specific information. + 9 This is referred to as event-driven programming, which is more efficient then every program + 10 polling linuxcnc at the same time. + 11 GladeVCP, Gscreen, Gmoccapy and QtVCP use GStat extensively. + 12 GStat is in the hal_glib module 13 14 == Overview 15 16 First a program imports the hal_glib module and instantiates GStat. + 17 Then it 'connects' to the messages it wishes to monitor. + 18 GStat checks linuxcnc's status every 100ms and if there are differences from + 19 the last check, it will send a callback message to all the connected programs + 20 with the current status. + 21 When GStat calls the registered function, it sends the GStat object plus any return codes from the message. + 22 typical code signatures: + 23 [source,python] 24 ---- 25 GSTAT.connect('MESSGAE-TO-LISTEN-FOR', FUNCTION_TO_CALL) 26 27 def FUNCTION_TO_CALL(gstat_object, return_codes): 28 ---- 29 30 Often LAMBDA is used to strip the GSTAT object and manipulate the return codes): + 31 32 [source,python] 33 ---- 34 GSTAT.connect('MESSGAE-TO-LISTEN-FOR', lambda o, return: FUNCTION_TO_CALL(not return)) 35 36 def FUNCTION_TO_CALL(return_codes): 37 ---- 38 39 == Sample GStat Code 40 41 There are some basic patterns for using GStat, depending on what library + 42 You are using them in. + 43 If using GStat with Gladevcp, Gscreen, or Qtvcp, the gobject library is not needed, + 44 Those toolkits already set up Gobject. + 45 46 === Sample HAL component code pattern 47 This program creates two HAL pins that output the status + 48 of G20/G21. 49 50 [source,python] 51 ---- 52 #!/usr/bin/env python 53 54 import hal 55 from hal_glib import GStat 56 import gobject 57 GSTAT = GStat() 58 59 # callback to change HAL pin state 60 def mode_changed(obj, data): 61 h['g20'] = not data 62 h['g21'] = data 63 64 # Make a component and pins 65 h = hal.component("metric_status") 66 h.newpin("g20", hal.HAL_BIT, hal.HAL_OUT) 67 h.newpin("g21", hal.HAL_BIT, hal.HAL_OUT) 68 h.ready() 69 70 # connect a GSTAT message to a callback function 71 GSTAT.connect("metric-mode-changed",mode_changed) 72 73 # force GSTAT to initialize states 74 GSTAT.forced_update() 75 76 # loop till exit 77 try: 78 gobject.MainLoop().run() 79 except KeyboardInterrupt: 80 raise SystemExit 81 ---- 82 83 This would be loaded with 'loadusr python PATH-TO-FILE/FILENAME.py' + 84 or if you need to wait for the pins to be made before continuing: + 85 'loadusr python -Wn metric_status PATH-TO-FILE/FILENAME.py' + 86 The pins would be: 'metric_status.g20' and 'metric_status.g21' + 87 88 === Sample GladeVCP python extension code pattern 89 This file assumes there are three GTK labels named: + 90 state_label + 91 e_state_label + 92 interp_state_label + 93 94 [source,python] 95 ---- 96 #!/usr/bin/env python 97 98 from hal_glib import GStat 99 GSTAT = GStat() 100 101 class HandlerClass: 102 103 def __init__(self, halcomp, builder, useropts): 104 self.builder = builder 105 106 GSTAT.connect("state-estop",lambda w: self.update_estate_label('ESTOP')) 107 GSTAT.connect("state-estop-reset",lambda w: self.update_estate_label('RESET')) 108 109 GSTAT.connect("state-on",lambda w: self.update_state_label('MACHIBE ON')) 110 GSTAT.connect("state-off",lambda w: self.update_state_label('MACHINE OFF')) 111 112 GSTAT.connect("interp-paused",lambda w: self.update_interp_label('Paused')) 113 GSTAT.connect("interp-run",lambda w: self.update_interp_label('Run')) 114 GSTAT.connect("interp-idle",lambda w: self.update_interp_label('Idle')) 115 116 def update_state_label(self,text): 117 self.builder.get_object('state_label').set_label("State: %s" % (text)) 118 119 def update_estate_label(self,text): 120 self.builder.get_object('e_state_label').set_label("E State: %s" % (text)) 121 122 def update_interp_label(self,text): 123 self.builder.get_object('interp_state_label').set_label("Interpeter State: %s" % (text)) 124 125 def get_handlers(halcomp,builder,useropts): 126 return [HandlerClass(halcomp,builder,useropts)] 127 ---- 128 == Messages 129 130 *periodic* :: '(returns nothing)' - 131 sent every 100 ms. 132 133 *state-estop* :: '(returns nothing)' - 134 Sent when linuxcnc is goes into estop. 135 136 *state-estop-reset*:: '(returns nothing)' - 137 Sent when linuxcnc comes out of estop. 138 139 *state-on* :: '(returns nothing)' - 140 Sent when linuxcnc is in machine on state. 141 142 *state-off*:: '(returns nothing)' - 143 Sent when linuxcnc is in machine off state. 144 145 *homed* :: '(returns string)' - 146 Sent as each joint is homed. 147 148 *all-homed* :: '(returns nothing)' - 149 Sent when all defined joints are homed. 150 151 *not-all-homed* :: '(returns string)' - 152 Sends a list of joints not currently homed. 153 154 *override_limits_changed* :: '(returns string)' - 155 Sent if linuxcnc has been directed to override it's limits. 156 157 *hard-limits-tripped* :: '(returns bool, Python List)' - 158 Sent when any hard limit is tripped. 159 bool indicates if any limit is tripped, the list shows all available joint's current limit values. 160 161 *mode-manual* :: '(returns nothing)' - 162 Sent when linuxcnc switches to manual mode. 163 164 *mode-mdi* :: '(returns nothing)' - 165 Sent when linuxcnc switches to mdi mode. 166 167 *mode-auto* :: '(returns nothing)' - 168 Sent when linuxcnc switches to auto mode. 169 170 *interp-run* :: '(returns nothing)' - 171 Sent when linuxcnc's interpreter is running an MDI or program. 172 173 *interp-idle* :: '(returns nothing)' - 174 Sent when linuxcnc's interpreter idle. 175 176 *interp-paused* :: '(returns nothing)' - 177 Sent when linuxcnc's interpreter is paused. 178 179 *interp-reading* :: '(returns nothing)' - 180 Sent when linuxcnc's interpreter is reading. 181 182 *interp-waiting* :: '(returns nothing)' - 183 Sent when linuxcnc's interpreter is waiting. 184 185 *jograte-changed* :: '(returns float)' - 186 Sent when jog rate has changed. + 187 Linuxcnc does not have an internal jog rate. + 188 This is GStat's internal jog rate. + 189 It is expected to be in the machine's native units regardless of the current unit mode . 190 191 *jograte-angular-changed* :: '(returns float)' - 192 Sent when the angular jog rate has changed. + 193 Linuxcnc does not have an internal angular jog rate. + 194 This is GStat's internal jog rate. + 195 It is expected to be in the machine's native units regardless of the current unit mode . 196 197 *jogincrement-changed* :: '(returns float)' - 198 Sent when jog increment has changed. + 199 Linuxcnc does not have an internal jog increment. + 200 This is GStat's internal jog increment. + 201 It is expected to be in the machine's native units regardless of the current unit mode . 202 203 *jogincrement-angular-changed* :: '(returns float)' - 204 Sent when angular jog increment has changed. + 205 Linuxcnc does not have an internal angular jog increment. + 206 This is GStat's internal angular jog increment. + 207 It is expected to be in the machine's native units regardless of the current unit mode . 208 209 *program-pause-changed* :: '(returns bool)' - 210 Sent when program is paused/unpaused. 211 212 *optional-stop-changed* :: '(returns bool)' - 213 Sent when optional stop is set/unset 214 215 *block-delete-changed* :: '(returns bool)' - 216 sent when block delete is set/unset. 217 218 *file-loaded* :: '(returns string)' - 219 Sent when linuxcnc has loaded a file 220 221 *reload-display* :: '(returns nothing)' - 222 Sent when there is a request to reload the display 223 224 *line-changed* :: '(returns integer)' - 225 Sent when linuxcnc has read a new line. + 226 Linuxcnc does not update this for every type of line. 227 228 *tool-in-spindle-changed* :: '(returns integer)' - 229 Sent when the tool has changed. 230 231 *tool-info-changed* :: '(returns python object)' - 232 Sent when current tool info changes. 233 234 *current-tool-offset* :: '(returns python object)' - 235 Sent when the current tool offsets change. 236 237 *motion-mode-changed* :: '(returns integer)' - 238 Sent when motion's mode has changed 239 240 *spindle-control-changed* :: '(returns bool, integer)' - 241 Sent when spindle direction or running status changes. 242 243 *current-feed-rate* :: '(returns float)' - 244 Sent when the current feed rate changes. 245 246 *current-x-rel-position* :: '(returns float)' - 247 Sent when the X relative position changes. 248 249 *current-position* :: '(returns pyobject, pyobject, pyobject)' - 250 Sent as the current positions changes. + 251 returns tuples of position,relative position and distance-to-go. 252 253 *current-z-rotation* :: '(returns float)' - 254 Sent as the current rotatated angle around the Z axis changes + 255 256 *requested-spindle-speed-changed* :: '(returns float)' - 257 Sent when the current requested RPM changes 258 259 *actual-spindle-speed-changed* :: '(returns float)' - 260 Sent when the actual RPM changes based on the HAL pin 'spindle.0.speed-in'. + 261 262 *spindle-override-changed* :: '(returns float)' - 263 Sent when the spindle override value changes + 264 in percent 265 266 *feed-override-changed* :: '(returns float)' - 267 Sent when the feed override value changes + 268 in percent 269 270 *rapid-override-changed* :: '(returns float)' - 271 Sent when the rapid override value changes + 272 in percent 0-100 273 274 *max-velocity-override-changed* :: '(returns float)' - 275 Sent when the maximum velocity override value changes + 276 in units per minute + 277 278 *feed-hold-enabled-changed* :: '(returns bool)' - 279 Sent when feed hold status changes 280 281 *itime-mode* :: '(returns bool)' - 282 Sent when G93 status changes + 283 (inverse time mode) 284 285 *fpm-mode* :: '(returns bool)' - 286 Sent when G94 status changes + 287 (feed per minute mode) 288 289 *fpr-mode* :: '(returns bool)' - 290 Sent when G95 status changes + 291 (feed per revolution mode) 292 293 *css-mode* :: '(returns bool)' - 294 Sent when G96 status changes + 295 (constant surface feed mode) 296 297 *rpm-mode* :: '(returns bool)' - 298 Sent when G97 status changes + 299 (constatnt RPM mode) 300 301 *radius-mode* :: '(returns bool)' - 302 Sent when G8 status changes + 303 display X in radius mode 304 305 *diameter-mode* :: '(returns bool)' - 306 Sent when G7 status changes + 307 display X in Diameter mode 308 309 *flood-changed* :: '(returns bool)' - 310 Sent when flood coolant state changes. 311 312 *mist-changed* :: '(returns bool )' - 313 Sent when mist coolant state changes. 314 315 *m-code-changed* :: '(returns string)' - 316 Sent when active M codes change 317 318 *g-code-changed* :: '(returns string)' - 319 Sent when active G code change 320 321 *metric-mode-changed* :: '(returns bool)' - 322 Sent when G21 status changes 323 324 *user-system-changed* :: '(returns string)' - 325 Sent when the reference coordinate system (G5x) changes 326 327 *mdi-line-selected* :: '(returns string, string)' - 328 intended to be sent when an MDI line is selected by user. + 329 This depends on the widget/libraries used. + 330 331 *gcode-line-selected* :: '(returns integer)' - 332 intended to be sent when a gcode line is selected by user. + 333 This depends on the widget/libraries used. + 334 335 *graphics-line-selected* :: '(returns integer)' - 336 intended to be sent when graphics line is selected by user. + 337 This depends on the widget/libraries used. + 338 339 *graphics-gcode-error* :: '(returns string)' - 340 intended to be sent when a gcode error is found when loading. + 341 This depends on the widget/libraries used. + 342 343 *graphics-gcode-properties* :: '(returns string)' - 344 intended to be sent when gcode is loaded. + 345 This depends on the widget/libraries used. + 346 347 *graphics-view-changed* :: '(returns string)' - 348 intended to be sent when graphics view is changed. + 349 This depends on the widget/libraries used. + 350 351 *mdi-history-changed* :: '(returns None)' - 352 intended to be sent when an MDI history needs to be reloaded. + 353 This depends on the widget/libraries used. + 354 355 *machine-log-changed* :: '(returns None)' - 356 intended to be sent when machine log has changed. + 357 This depends on the widget/libraries used. + 358 359 *update-machine-log* :: '(returns string, string)' - 360 intended to be sent when updating the machine. + 361 This depends on the widget/libraries used. + 362 363 *move-text-lineup* :: '(returns None)' - 364 intended to be sent when moving the cursor one line up in gcode display. + 365 This depends on the widget/libraries used. + 366 367 *move-text-linedown* :: '(returns None)' - 368 intended to be sent when moving the cursor one line down in gcode display. + 369 This depends on the widget/libraries used. + 370 371 *dialog-request* :: '(returns python dict)' - 372 intended to be sent when requesting a gui dialog. + 373 It uses a python dict for communication. + 374 The dict must include the following keyname pair: + 375 * NAME: 'requested dialog name' + 376 The dict usually has more keyname pair - it depends on the dialog. + 377 dialogs return information using a general message + 378 This depends on the widget/libraries used. + 379 380 *focus-overlay-changed* :: '(returns bool, string, python object)' - 381 intended to be sent when requesting an overlay to be put over the display. + 382 This depends on the widget/libraries used. + 383 384 *play-sound* :: '(returns string)' - 385 intended to be sent when requesting a specific sound file to be played. + 386 This depends on the widget/libraries used. + 387 388 *virtual-keyboard* :: '(returns string)' - 389 intended to be sent when requesting a on screen keyboard. + 390 This depends on the widget/libraries used. + 391 392 *dro-reference-change-request* :: '(returns integer)' - 393 intended to be sent when requesting a DRO widget to change it's reference. + 394 0 = machine, 1 = relative, 3 = distance-to-go + 395 This depends on the widget/libraries used. + 396 397 *show-preferences* :: '(returns None)' - 398 intended to be sent when requesting the screen preferences to be displayed. + 399 This depends on the widget/libraries used. + 400 401 *shutdown* :: '(returns None)' - 402 intended to be sent when requesting linuxcnc to shutdown. + 403 This depends on the widget/libraries used. + 404 405 *error* :: '(returns integer, string)' - 406 intended to be sent when an error has been reported . + 407 integer represents the kind of error. ERROR, TEXT or DISPLAY + 408 string is the actual error message. + 409 This depends on the widget/libraries used. + 410 411 *general* :: '(returns python dict)' - 412 intended to be sent when message must be sent that is not covered by a more specific message. + 413 General message should be used a sparsely as reasonable because all object connected to it will have to parse it. + 414 It uses a python dict for communication. + 415 The dict should include and be checked for a unique id keyname pair: + 416 * ID: 'UNIQUE_ID_CODE' + 417 The dict usually has more keyname pair - it depends on implementation. + 418 419 *forced-update* :: '(returns None)' - 420 intended to be sent when one wishes to initialize or arbitrarily update an object. + 421 This depends on the widget/libraries used. + 422 423 == Functions 424 These are convenience functions that are commonly used in programming 425 426 *set_jograte* :: '(float)' - 427 Linuxcnc has no internal concept of jog rate -each GUI has it's own. + 428 This is not always convenient. + 429 This function allows one to set a jog rate for all objects connected to the + 430 signal 'jograte-changed'. + 431 It defaults to 15 + 432 GSTAT.set_jog_rate(10) would set the jog rate to 10 machine-units-per-minute and emit the jograte-changed signal. + 433 434 *get_jograte()* :: '(Nothing)' - 435 x = GSTAT.get_jograte would return GSTAT's current internal jograte. 436 437 *set_jograte_angular* :: '(float)' - 438 439 *get_jograte_angular* :: '(None)' - 440 441 *set_jog_increment_angular* :: '(float, string)' - 442 443 *get_jog_increment_angular* :: '(None)' - 444 445 *set_jog_increments* :: '(float, string)' - 446 447 *get_jog_increments* :: '(None)' - 448 449 *is_all_homed* :: '(nothing)' - 450 This will return the current state of all_homed (BOOL). 451 452 *machine_is_on* :: '(nothing)' - 453 This will return the current state of machine (BOOL). 454 455 *estop_is_clear* :: '(nothing)' - 456 This will return the state of Estop (BOOL) 457 458 *set_tool_touchoff* :: '(tool,axis,value)' - 459 This command will record the current mode, switch to MDI mode, + 460 invoke the MDI command: G10 L10 P[TOOL] [AXIS] [VALUE] + 461 wait for it to complete + 462 invoke G43 + 463 wait for it to complete + 464 switch back to the original mode. + 465 466 *set_axis_origin* :: '(axis,value)' - 467 This command will record the current mode, switch to MDI mode, + 468 invoke the MDI command: G10 L20 P0 [AXIS] [VALUE] + 469 wait for it to complete + 470 switch back to the original mode. + 471 emit a 'reload-display' signal. + 472 473 *do_jog* :: '(axis_number,direction, distance)' - 474 This will jog an axis continuously or at a set distance. + 475 You must be in the proper mode to jog. 476 477 *check_for_modes* :: '(mode)' - 478 This function checks for required linuxcnc mode. + 479 It returns a python tuple (state, mode) + 480 mode will be set the mode the system is in + 481 state will set to: + 482 false if mode is 0 + 483 false if machine is busy + 484 true if linuxcnc is in the requested mode + 485 None if possible to change, but not in requested mode + 486 487 *get_current_mode* :: '(nothing)' - 488 returns integer: the current linuxcnc mode. + 489 490 *set_selected_joint* :: '(integer)' - 491 records the selected joint number internally. + 492 requests the joint to be selected by emitting the + 493 'joint-selection-changed' message. + 494 495 *get_selected_joint* :: '(None)' - 496 returns integer representing the internal selected joint number. + 497 498 *set_selected_axis* :: '(string)' - 499 records the selected axis letter internally. + 500 requests the axis to be selected by emitting the + 501 'axis-selection-changed' message. + 502 503 *get_selected_axis* :: '(None)' - 504 returns string representing the internal selected axis letter. + 505 506 *is_man_mode* :: '(None)' - 507 508 *is_mdi_mode* :: '(None)' - 509 510 *is_auto_mode* :: '(None)' - 511 512 *is_on_and_idle* :: '(None)' - 513 514 *is_auto_running* :: '(None)' - 515 516 *is_auto_paused* :: '(None)' - 517 518 *is_file_loaded* :: '(None)' - 519 520 *is_metric_mode* :: '(None)' - 521 522 *is_spindle_on* :: '(None)' - 523 524 *shutdown* :: '(None)' - 525 526 == Known Issues 527 528 Some status points are reported wrongly during a running program. + 529 This is because the interpreter runs ahead of the current position of a running program. + 530 This will hopefully be resolved with the merge of state-tags branch. + 531 532