RepRapFirmware Python API
-
For a project I required a basic API to connect to RRF boards via HTTP, and wrote a small wrapper (I didn't find anything alike):
https://github.com/Spiritdude/RepRapFirmwarePyAPI
import RepRapFirmwareAPI rrf = RepRapFirmwareAPI.RRFRestAPI("192.168.0.12") resp = rrf.gcode("M122") # synchronous # Note: type(resp) is either dict containing data, or str rrf.gcode("M122","async") # asynchronous resp = rrf.reply() rrf.upload("test.gcode","/gcodes/test.gcode") rrf.print("/gcodes/test.gcode") rrf.print_status()
gcode() by default operates synchronous, it waits for a sensible reply, but the behavior can be changed; also, reply() by default is asynchronous, but can be changed as well.
Note: the API is very experimental, if you adapt/adopt it, please check back the github the next weeks (e.g. until March 2023) to follow changes, e.g. in behavior.
Any feedback to improve Python API is appreciated.
@T3P3Tony or @dc42 as of current RRF there is no support for HTTP sessions - so when I send some command via HTTP and poll with
/rr_reply
, for a long running gcode() command (like heating or homing), the web-GUI running in a browser likely interferes? -
@xyzdims thanks for sharing this. I will also tag @chrishamm in for his input on http sessions timing out for long running commands and how that interacts with DWC.
-
@xyzdims said in RepRapFirmware Python API:
as of current RRF there is no support for HTTP sessions
Are you referring to a different type of session support than the one described here which is established when using rr_connect?
From memory I think a once established, the standard session timeout is 8 seconds.
-
@MintyTrebor so all commands like
/rr_gcode
which are shorter than 8s to execute, I get reliable response when I start with/rr_connect
as session initiator; for homing or heating the nozzle via/rr_gcode
I exceed the 8s, so the response via/rr_reply
likely will be caught by DWC or whoever catches it first, correct? -
@xyzdims I think you may need to re-assess what you class as a response.
For example G28 executes a macro, which then runs a series of other gcode commands - which results in a status changes to values in the Object Model (eg. move.axes[0].homed). DWC will execute the G28 command, and then monitor the OM looking for the associated status change(s), it does not look for a single response like "Homed". Many commands result to a change in the OM, and not a response as you have interpreted it. EG - if you wanted to execute G28 from your program you would probably need to poll the OM until all move.axes[#].homed = true, or an error/response msg is generated.
The best way I found to decode how DWC uses the rest api, is to monitor the network tab in your browsers developer console, where you can see how DWC sends commands and polls the OM.
Note: error/warning/info/response msgs are handled by monitoring a OM key value for increments. Every increment in the key value indicates new msg(s) have been generated. DWC monitors this and then retrieves the msg contents for display. I believe this is why you think DWC is "intercepting" your results - its not, DWC is just seeing an increment in the message flag OM Key and doing what it is supposed to do.
I hope this makes sense.
-
Just a thought. What is the objective for your project ?
If its a general purpose wrapper, that's one thing. If its for a specific purpose, there may be different ways to achieve the goal.
-
@MintyTrebor thanks a lot for the explanation.
I need to ponder on this a bit, to see in which direction I adapt the things you said. In a way, the RestAPI is lower level than a USB connection, which helps DWC but for me it likely means I need to reimplement a layer which RRF does for USB connection.
I don't mind about
G28
special case, but anything long running commands like heating are more critical, and I end up with various special cases. -
@stuartofmt I have two use cases: https://github.com/Spiritdude/Prynt3r is a CLI tool (a rewrite of Print3r), there I have two modes:
- to print .gcode, right now I upload and print, and then poll on print_status until the end of print, and remove the file again - works fine
- to launch a CLI console, where I can send individual gcodes, this helps me to tune printers, there I found it hard to rely on
/rr_reply
response - anyway, before I go ahead to I need to reflect on @MintyTrebor feedback more
Context: I do most of my development via CLI, and Prynt3r/Print3r is
- slicer agnostic, it supports 10+ slicers
- all my prints are logged, with all settings - I can go back 5+ years to see what settings a print had (I attach QR codes to prints identifying the print with the log file), etc
- local (USB) and remote printers (TCP or RRF, hence the the library) are supported, as "TCP" I use
ser2net
andsocat
combination, which makes it all look serial from within Prynt3r
and now I wanted "native" RRF support using HTTP layer.
-
@xyzdims Did you see my OpenAPI definition? That should make it quite easy to wrap potentially missing HTTP calls as Python methods.
The rr_ API requires repeated queries within 8 seconds, else the active session times out.
For .NET there's already my DuetHttpClient library which supports both SBC and standalone mode and keeps the session(s) alive automatically.
-
-