DSF-APIs: pydsfapi and godsfapi
-
I'm having a go at writing some automation for my printer using the DSF IPC socket by using the handy DSF-APIs. Specifically I'm using pydsfapi: https://github.com/Duet3D/DSF-APIs.git
I'm running all the latest stable releases:
RRF 3.2.2, DSF 3.2.2, DSF-APIs/pydsfapi 3.1.3This is somewhat of an experience report, bug report, feature request mix - based on my last two weeks of working with my Duet2WiFi + SBC printer.
I'd like to see pydsfapi published as proper package on PyPi! Would make installing it a bit simpler. Instead of cloning the repo, and running
python3 setup.py install
, one would simply install it with pip.When I start a connection, duetcontrolserver write the following log message:
[warn] IPC#7: Client with outdated protocol version connected (got 8, want 10)
And yes indeed, pydsfapi only implements version 8 of the IPC protocol. This problem also affects gosfapi.The Subscribe connection in pydsfapi has a few odd quirks:
subscribe_connection.get_machine_model()
returns a slightly weird object with attributes for the top-level object model, i.e.,job
,heat
,state
. But not always inPATCH
mode. This means writing code is particularly verbose because we constantly have to check for the existence of these attributes first, before checking thedict
inside them. I think the simplest and cleanest approach would be to simply make themachinemodel.MachineModel
a fully workingdict
or very close to it.
So, instead of this:if hasattr("job", machine_model): if "fileName" in machine_model.job: ...
I'd like to see a cleaner & uniform way of accessing the object model:
if "job" in machine_model: if "fileName" in machine_model.job: ...
The "double-import" path of pydsfapi is "unexpected":
from pydsfapi import pydsfapi # odd import pydsfapi # more natural way of importing under python
I couldn't find a clear changelog for DSF/DCS - otherwise I would have sent a PR to implement the latest protocol. @wilriker any chance you could bring the API packages pydsfapi and godsfapi up to date with the latest protocol definitions?
Unfortunately this JSON-based IPC protocol is not documented, and the readme simply refers to "read the code" and "code documentation" for the C#-based DSF itself. I would have loved to see a dedicated docs page listing all JSON messages being exchanged and expected in the various connections and states.
While developing my automation, I managed to crash DCS a few times, getting
[error] IPC#11: Terminating connection due to unexpected exception
and other errors. I also managed to completely "halt" my printer, meaning the currently processing job simply stopped executing, only a reboot+reset helped (hard to reproduce, but M122 said something that it is executing one of my macros - but it never did...)
Some issues might be caused by me simply passing wrong arguments - and python being duck-typing - pydsfapi simply accepting them and encoding it into JSON for DSC, which then chokes on them. So ideally there would be more data validation to raise an exception back to the user, instead of having DSC crash.Is using the API generally considered safe and stable? I'm a bit paranoid that I might crash the firmware/SBC and then my heaters burn down everything...
-
@resam I don't maintain the Python API client so I cannot really comment on the internals. Model subscribers in patch mode get either the full object model or the requested filtered model props after connecting so it should be safe to assume that props in the dict are already present. List items may change, though.
There is some more documentation about the IPC API in the README where some JSON objects are described, see here. In general DCS should not shut down because of an API error or invalid command. It's right that it should output an error and terminate the client connection when invalid data is supposed to be processed, but DCS should continue operating after that.
When a code is intercepted, a client must send back a definite action to DCS to avoid locking up the G-code stream. If a client disconnects while DCS is still waiting for an interception result, DCS should resume the code execution. I already wrote a few plugins (although obviously in C# and not Python) and I can confirm the API works well in general. But if you do find errors, feel free to submit bug reports on GitHub and I'll comment on them there.