Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 59 additions & 10 deletions scripts/octocmd
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import pprint

logger = None


def configure_logger(name=None, debug=False):
global logger
name = name or __name__
Expand All @@ -26,6 +27,7 @@ def configure_logger(name=None, debug=False):
ch.setFormatter(formatter)
logger.addHandler(ch)


def which(program):
def is_qualified_exe(fpath):
return len(os.path.split(fpath)[0]) and os.path.isfile(fpath) and os.access(fpath, os.X_OK)
Expand All @@ -44,10 +46,12 @@ def which(program):
return best_guess
return None


def touch(fname, times=None):
with open(fname, 'a'):
os.utime(fname, times)


class TransformPipeline(object):
def __init__(self, processors=None, **kw):
self.output_dir = kw.get("output_dir", '.')
Expand All @@ -67,7 +71,7 @@ class TransformPipeline(object):
continue
processors.append(cls)
return [proc(**self.init_kw) for proc in processors]

def get_pipeline(self, inputfn, outputfn, level=1):
inputext = os.path.splitext(inputfn)[-1]
outputext = os.path.splitext(outputfn)[-1]
Expand Down Expand Up @@ -99,6 +103,7 @@ class TransformPipeline(object):
raise RuntimeError, "Could not transform %s -> %s" % (inputfn, outputfn)
self.run_pipeline(pipeline, **kw)


class PrintProcess(object):
FunctionTemplate = re.compile("transform_(.+)_to_(.+)")

Expand All @@ -124,10 +129,11 @@ class PrintProcess(object):
if self.phony or self.stale(inputfn, outputfn):
self._transform(inputfn, outputfn, **args)
return self.stale(inputfn, outputfn)

def _transform(self, inputfn, outputfn, **args):
touch(outputfn)


class PrintCommand(PrintProcess):
Command = "__command__"
CommandPath = None
Expand All @@ -151,7 +157,8 @@ class PrintCommand(PrintProcess):
msg = "running: %s" % cmd
logger.debug(msg)
os.system(cmd)



class Cura_API(PrintCommand):
Command = "cura"

Expand All @@ -169,6 +176,7 @@ class Cura_API(PrintCommand):
def transform_stl_to_gcode(self, *args, **kw):
self.transform(*args, **kw)


class OpenSCAD_API(PrintCommand):
Command = "openscad"

Expand All @@ -190,6 +198,7 @@ class OpenSCAD_API(PrintCommand):
def transform_scad_to_stl(self, *args, **kw):
self.transform(*args, **kw)


class OctoPrint_API(PrintProcess):
def __init__(self, *args, **kw):
super(OctoPrint_API, self).__init__(*args, phony=True, **kw)
Expand Down Expand Up @@ -249,7 +258,7 @@ class OctoPrint_API(PrintProcess):

def get_location(self, sdcard=False, **kw):
return "sdcard" if sdcard else "local"

def stale(self, inputfn, outputfn, sdcard=False, filename=None, **kw):
stale = True
filename = filename or os.path.split(inputfn)[-1]
Expand All @@ -258,12 +267,12 @@ class OctoPrint_API(PrintProcess):
if file_info:
stale = os.path.getmtime(inputfn) > file_info["date"]
return stale

## high level
def has_file(self, filename, **kw):
info = self.get_file(filename, **kw)
return bool(info)

def get_file(self, filename, **kw):
location = self.get_location(**kw)
url = str.join('/', ("files", location, filename))
Expand All @@ -284,7 +293,7 @@ class OctoPrint_API(PrintProcess):
fh = open("content.txt", 'w')
fh.write(str(res.content))
return self.check_response(res, 201, **kw)

def delete_file(self, filename, **kw):
location = self.get_location(**kw)
url = "files/%s/%s" % (location, filename)
Expand All @@ -295,6 +304,18 @@ class OctoPrint_API(PrintProcess):
res = self.get("printer")
return self.check_response(res, 200, **kw)

def restart_job(self, **kw):
res = self.post("job", {"command": "restart"})
return self.check_response(res, 204, **kw)

def pause_job(self, **kw):
res = self.post("job", {"command": "pause"})
return self.check_response(res, 204, **kw)

def cancel_job(self, **kw):
res = self.post("job", {"command": "cancel"})
return self.check_response(res, 204, **kw)

## transform API
def _transform(self, inputfn, outputfn, **kw):
filename = os.path.split(inputfn)[-1]
Expand Down Expand Up @@ -327,7 +348,8 @@ class OctoPrint_API(PrintProcess):

def transform_gcode_to_select(self, inputfn, outputfn, **kw):
kw["select"] = "1"
self.transform(inputfn, outputfn, **kw)
self.transform(inputfn, outputfn, **kw)


def load_config(fn, error=True):
try:
Expand All @@ -339,12 +361,14 @@ def load_config(fn, error=True):
raise RuntimeError, msg
return {}


def save_config(fn, config):
msg = "Saving config file to '%s'" % fn
print msg
fh = open(fn, 'w')
fh.write(json.dumps(config, sort_keys=True, indent=4))


def get_cli():
def standard_arg_set(sp):
sp.add_argument('-S', '--openscad_exe', help='path to OpenSCAD')
Expand All @@ -367,6 +391,15 @@ def get_cli():
# create the parser for the "status" command
sp = subparsers.add_parser('status', help='printer status')

# create the parser for the "restart" command
sp = subparsers.add_parser('restart', help='restart current job')

# create the parser for the "pause" command
sp = subparsers.add_parser('pause', help='pause current job')

# create the parser for the "cancel" command
sp = subparsers.add_parser('cancel', help='cancel current job')

# create the parser for the "print" command
sp = subparsers.add_parser('print', help='print a file')
standard_arg_set(sp)
Expand Down Expand Up @@ -395,6 +428,7 @@ def get_cli():

return args


def process_status(args):
op = OctoPrint_API(**args.__dict__)
res = op.get_state(error=True)
Expand All @@ -414,7 +448,7 @@ def process_status(args):
rpt += '%s%s: ' % (header(level), key)
if "text" in obj[key]:
rpt += '%s\n' % obj[key]["text"]
elif any([type(i) == dict for i in val.values()]):
elif any([type(i) == dict for i in val.values()]):
rpt += '\n'
rpt += format_status(val, level + 1)
vals = []
Expand All @@ -429,6 +463,7 @@ def process_status(args):

print format_status(res)


def process_init(args):
def test_config(config):
op = OctoPrint_API(config=config)
Expand All @@ -455,6 +490,7 @@ def process_init(args):
complete = len(answer) and (answer[0].lower() == 'y')
save_config(args.config, cache)


def process_target(args):
targets = []
infn = args.input_filename[0]
Expand All @@ -468,16 +504,29 @@ def process_target(args):
for targetfn in targets:
pipe.transform(infn, targetfn)


def process(args):
if args.mode == "status":
args.config = load_config(args.config)
process_status(args)
elif args.mode == "restart":
args.config = load_config(args.config)
op = OctoPrint_API(**args.__dict__)
op.restart_job(error=True)
elif args.mode == "pause":
args.config = load_config(args.config)
op = OctoPrint_API(**args.__dict__)
op.pause_job(error=True)
elif args.mode == "cancel":
args.config = load_config(args.config)
op = OctoPrint_API(**args.__dict__)
op.cancel_job(error=True)
elif args.mode in ("print", "upload", "select"):
args.config = load_config(args.config)
process_target(args)
elif args.mode in ("init"):
process_init(args)

if __name__ == "__main__":
args = get_cli()
configure_logger("octocmd", debug=args.debug)
Expand Down