linuxcnc/lib/python/tooldb.py
Dewey Garrett 2dbb2f640f tooldata: refactor and add database intfc db73
Note: this branch is force pushed, rebased to master at 890187289

================================================================
This commit refactors internal tool data handling to:
1) Update and consolidate functions in a new directory:
     src/emc/tooldata
2) Define an applications interface: src/emc/tooldata/tooldata.hh
3) Support a new interface to a user-provided tool database
   management program specified by [EMCIO]DB_PROGRAM
4) Use a new mmapped tooldata interface between
   EMCIO and TASK while maintaining number of allowed
   pockets specified by CANON_POCKETS_MAX=1001
5) Deprecate tooldata in nml messages between EMCIO and TASK
   (legacy nml message method remains available using
     configure --enable-toolnml until removal)
6) Minimize impact to current users of master branch and
   continue to pass the suite of runtests on all supported
   buildbot machines.
7) Clarify program variable names that use a sequential
   index (idx) for accessing internal tooldata.
   Note: some legacy variable names like:
      pocketPrepped, selected_pocket,current_pocket
   are still used in a few places because of their inclusion
   in fielded user remap scripts or the tests suite.
   These items may be renamed in the future.

================================================================
Change Summary:
 1) new directory: src/emc/tooldata
    tooldata.hh  ------------ api
    tooldata_common.cc  ----- shared functions
    tooldata_mmap.cc  ------- mmap tooldata
    tooldata_nml.cc  -------- nml tooldata
    tooldata_db.cc  --------- database interface functions
    tool_watch.cc  ---------- test utility
    tool_mmap_read.cc  ------ test utility for mmap

 3) updated docs:
    docs/src/getting-started/updating-linuxcnc.txt
    docs/src/config/ini-config.txt
    docs/src/code/code-notes.txt
    docs/src/gcode/overview.txt
    docs/src/gcode/tool-compensation.txt
    docs/src/remap/remap.txt
    docs/man1/iocontrol*.1
    docs/src/tooldatabase/tooldatabase.txt (new)

 3) removed (consolidated into other files):
       src/emc/task/iotaskintf.cc
       src/emc/ini/initool.hh
       src/emc/ini/initool.cc
       src/emc/rs274ngc/tool_parse.h
       src/emc/rs274ngc/tool_parse.cc
       src/emc/toolstore/

 4) emccanon call: removed GET_EXTERNAL_POCKETS_MAX
    (superseded by CANON_POCKETS_MAX)

 5) hal: params to pins:
    iocontrol.N.tool-prep-index

 6) gui updates (axis gui only)
    Print message if both [EMCIO]TOOL_TABLE and DB_PROGRAM
    are specified.  Allow specifying tooleditor for a DB_PROGRAM
    Issue message for db_program/tool_table ambiguities

 7) simulation configs:
      configs/sim/axis/db_demo/db_ran.ini
      configs/sim/axis/db_demo/db_nonran.ini

================================================================
Notes:
    1) Testing has been aided by the extensive set of tests
       exercised by the runtests program employed to ensure
       the integrity of buildbot created deb packages.  However,
       numerous functions are NOT tested by the runtests suite.
       Examples:
         a) remapped tool handling
         b) user-interfaces (ui) support for tool changes
         c) iov2 (ioControl_v2.cc -- no maintainer, deprecated)
    2) Use of the mmapped interface between EMCIO and TASK
       reduces the EMC_TOOL_STAT message size from 112224 bytes
       to 224 bytes (64bit architecture)
    3) The complete toolTable[] data for all (1001)
       CANON_POCKETS_MAX is no longer available should someone
       implement a *remote* ui with TASK and EMCIO
       implemented on *separate* machines via networked (TCP)
       nml messages.  A single tool table instance for
       the current tool in spindle is included in the
       EMC_TOOL_STAT message.
2021-01-31 10:35:55 -07:00

121 lines
3.3 KiB
Python

import sys
# A python interface for LinuxCNC tool database usage
#Notes
# 1) host (linuxCNC) pushes commands to this program
# 2) all writes to stdout go to host
# (use stderr for debug prints)
#-----------------------------------------------------------
DB_VERSION = 'v1.0'
# Required data functions to be provided by user:
def tooldb_callbacks(tool_getter,tool_putter):
global get_tool, put_tool
get_tool = tool_getter
put_tool = tool_putter
def tooldb_tools(tool_list):
global tools
tools = tool_list
#-----------------------------------------------------------
# Interface functions
def do_reply(msg):
sys.stdout.write("%s\n"%msg)
sys.stdout.flush()
def nak_reply(msg):
global theline
sys.stdout.write("NAK %s <%s>\n"%(msg,theline))
sys.stdout.flush()
def tool_cmd(cmd,params):
if not len(params):
nak_reply("no toolno")
return
if len(params.split()) != 1:
nak_reply("too many parms")
return
try:
toolno = int(params)
except Exception as e:
nak_reply("non-integer toolno")
return
if toolno not in tools:
nak_reply("toolno out-of-range")
return
do_reply(get_tool(toolno))
def get_cmd(cmd,params):
for tno in tools:
try: do_reply(get_tool(tno))
except:
if (tno==0):
if debug: sys.stderr.write("no tool in spindle\n")
pass
do_reply("FINI (get_cmd)")
def put_cmd(cmd,params):
# note: checks are mainly for commandline debugging,
# expect host to always provide a valid toolline
uparams = params.upper()
if len(uparams) == 0:
raise Exception("put_cmd: requires tool entry line")
try:
toolno = int(uparams[0:uparams.index(" ")].strip("T"))
toolline = uparams
except Exception as e:
sys.stderr.write("put_cmd: %s:\n"%e)
raise Exception("put_cmd: failed to parse <%s>"%params)
# require at least "Tvalue Pvalue"
try: toolline.index("T");toolline.index(" P")
except Exception as e:
sys.stderr.write("put_cmd: %s:\n"%e)
raise Exception("put_cmd: failed to parse <%s>"%params)
put_tool(toolno,toolline)
do_reply("FINI (update recvd) %s"%params)
def unknown_cmd(cmd,params):
global theline
nak_reply("unknown cmd")
return
def do_cmd(line):
global debug
if debug: sys.stderr.write("!!line=<%s>\n"%line)
linelist = line.strip().split()
cmd = linelist[0]
params = ""
if len(linelist) > 1:
params = line.strip()[line.index(" "):].strip()
switcher = {
"g": get_cmd, # get (all tools)
"p": put_cmd, # put (update one tool)
"t": tool_cmd, # debug usage
}
thecmd = switcher.get(cmd) or unknown_cmd
thecmd(cmd,params)
def startup_ack():
global debug
debug = 0
do_reply("%s"%DB_VERSION);
if (len(sys.argv)>1 and sys.argv[1] == 'debug'): debug = 1
#-----------------------------------------------------------
global get_tool
global tools
theline = ""
def tooldb_loop():
startup_ack()
global theline
while True:
try:
theline=sys.stdin.readline().strip()
if (theline == ""): nak_reply("empty line")
else: do_cmd(theline)
except Exception as e:
nak_reply("_exception=%s"%e)