Hello!
I am developing on the Mr Beam Plugin for our commercial Laser Cutter.
Obviously compatibility of OctoPrint for generalised machine types has therefore been on our minds.
Our way of getting around it
The way we currently have it set up is a semi-total rewrite of the MachineComm
class and a subclass for Printer
(called Laser
). A complete re-write allows us to set completely new GCode commands, new machine states etc...
Ideally it would be best to have some extra abstraction layers for MachineCom
so it doesn't include hard-coded Gcode values or 3D printer behaviour / states.
Upgrade cycle
As we are upgrading to OctoPrint v1.4 , some of the states changed etc...
If in your plugin you have to modify that would recommend - if you can - to rely on the octoprint.util.comm.MachineCom
class as much as possible. Will make your life easier. Not necessarily inherit from it, but reference as much of your logic to the one that is already written in octoprint
itself.
Personal thoughts on general purpose CNC machines accepting GCode
When looking at the OctoPrint codebase, I am pretty confident that a Machine
class can be created. A Printer
would be a Machine
, composed of Part
s such as a PrintHead
, HeatBed
, Gantry
etc...
Each Part
has a unique ID. What would be nice is that you can refer to each part of a Machine
using my_machine['my_part_1']
or preferably my_machine.my_part_1
(using set_attribute)
Each part implements a behaviour (function) for the Machine
(do_homing, move_to, heat, start_laser ... ). Each action/behaviour is related to a default Part
(or groups of Part
s ?), but you could perform a homing with my_machine.non_default_gantry
using either
my_machine.non_default_gantry.home()
my_machine.home(part='non_default_gantry')
my_machine.home(part=my_machine.non_default_gantry)
A default MachineInterface
can create these functions for the machine as
Whether the MachineInterface
and Machine
classes are metaclasses, normal classes or even class decorators is completely up in the air right now. It will probably come down to an orchestra of those different types.
How it ties in with the standard.Printer
The Machine
, MachineInterface
and Part
can have their own folder in src/octoprint/machine/
and the Printer
/ PrinterInterface
would inherit from those and still keep their current place and form to maximise backwards compatibility.
Default Parts
Each Part
could have some attached settings to describe some behaviour. If all the required Part
s are implemented, one could describe a whole machine with some settings, in the same vein as described in foosel's previous comment
properties:
firmware: Smoothieware
parts:
gantry:
type: gantry
axis: 3 # or [x, y, z]
range_x: [0, 200]
range_y: [0, 300]
max_speed: 2000
jog: G0
extrude: G1
heatbed:
type: heatbed
read_temperature: M20
hotend1:
type: hotend
default: true
set_temperature: M104
hotend2:
type: hotend
set_temperature: M105
If the Machine
has enough Part
s to slice / print a file, you shouldn't need to create your own MyOtherMachine
class in a plugin. That will probably be necessary if you intend to use multiple redundant parts (yeah I'm thinking of the crazies who are using 2 hotends on the same gantry at a time haha)
As you might see I've started to write a tiny bit of code to see if it ain't ridiculous.
@foosel I hope this is good food for thoughts? What do you think?