Optional args (10 max) can be used to specify startup parameters for the [EMCIO]DB_PROGRAM DB_VERSION=v2.1 Interface is backwards compatible, but DB_VERSION is bumped in case applications used undocumented argv[1]==DB_VERSION that was originally passed to DB_PROGRAM
161 lines
4.7 KiB
Python
161 lines
4.7 KiB
Python
import sys
|
|
import traceback
|
|
|
|
# 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
|
|
# (caller: use stderr for debug prints)
|
|
#-----------------------------------------------------------
|
|
DB_VERSION = 'v2.1'
|
|
|
|
#-----------------------------------------------------------
|
|
# functions for import by user
|
|
# tooldb_callbacks
|
|
# tooldb_tools
|
|
# tooldb_loop
|
|
#-----------------------------------------------------------
|
|
|
|
def do_reply(msg):
|
|
sys.stdout.write("%s\n"%msg)
|
|
sys.stdout.flush()
|
|
|
|
def saveline(line):
|
|
global theline
|
|
theline = line
|
|
|
|
def currentline():
|
|
global theline
|
|
return theline
|
|
|
|
def nak_reply(msg):
|
|
theline = currentline()
|
|
if msg != "empty_line": sys.stderr.write(traceback.format_exc()+"\n")
|
|
sys.stdout.write("NAK %s <%s>\n"%(msg,theline))
|
|
sys.stdout.flush()
|
|
|
|
def tool_cmd(cmd,params):
|
|
# debug usage: return info for tool
|
|
# parms is toolno
|
|
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: msg = get_tool(tno)
|
|
except Exception as e:
|
|
nak_reply( "get_cmd():Exception:%s"%str(e))
|
|
return
|
|
try: do_reply(msg)
|
|
except:
|
|
if (tno==0):
|
|
if debug: sys.stderr.write("no tool in spindle\n")
|
|
pass
|
|
do_reply("FINI (get_cmd)")
|
|
|
|
def put_cmds(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("cmd=%s: requires tool entry line"%cmd)
|
|
try:
|
|
toolno = int(uparams[0:uparams.index(" ")].strip("T"))
|
|
toolline = uparams
|
|
except Exception as e:
|
|
sys.stderr.write("cmd=%s: %s:\n"%(cmd,e))
|
|
raise Exception("cmd=%s: failed to parse <%s>"%(cmd,params))
|
|
# require at least "Tvalue Pvalue"
|
|
try: toolline.index("T");toolline.index(" P")
|
|
except Exception as e:
|
|
sys.stderr.write("cmd=%s: %s:\n"%(cmd,e))
|
|
raise Exception("cmd=%s: failed to parse <%s>"%(cmd,params))
|
|
|
|
try:
|
|
if cmd == "p": put_tool( toolno,toolline)
|
|
elif cmd == "l": load_spindle( toolno,toolline)
|
|
elif cmd == "u": unload_spindle(toolno,toolline)
|
|
except Exception as e:
|
|
nak_reply( "cmd=%s: Exception:%s"%(cmd,str(e)))
|
|
return
|
|
do_reply("FINI (update recvd) %s"%params)
|
|
|
|
def unknown_cmd(cmd,params):
|
|
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 is everything after first " ":0
|
|
params = line.strip()[line.index(" "):].strip()
|
|
switcher = {
|
|
"g": get_cmd, # get (all tools)
|
|
"p": put_cmds, # put (update one tool offsets)
|
|
"u": put_cmds, # unload spindle
|
|
"l": put_cmds, # load spindle
|
|
"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
|
|
|
|
#-----------------------------------------------------------
|
|
# Begin functions that can be imported
|
|
|
|
def tooldb_callbacks(tool_getter,tool_putter,spindle_loader,spindle_unloader):
|
|
"""Specify callback functions"""
|
|
global get_tool, put_tool, load_spindle, unload_spindle
|
|
get_tool = tool_getter
|
|
put_tool = tool_putter
|
|
load_spindle = spindle_loader
|
|
unload_spindle = spindle_unloader
|
|
|
|
def tooldb_tools(tool_list):
|
|
"""Specify list = available toolnumers"""
|
|
global tools
|
|
tools = tool_list
|
|
|
|
def tooldb_loop():
|
|
"""Loop forever:
|
|
1) send startup acknowledgment
|
|
2) read line from stdino
|
|
3) parse line
|
|
execute command if valid
|
|
nak command if invalid
|
|
4) repeat
|
|
"""
|
|
startup_ack()
|
|
while True:
|
|
try:
|
|
line=sys.stdin.readline().strip()
|
|
|
|
saveline(line)
|
|
if (line == ""): nak_reply("empty_line")
|
|
else: do_cmd(line)
|
|
except BrokenPipeError: sys.stdout.close()
|
|
except Exception as e:
|
|
nak_reply("_exception=%s"%e)
|