Solved Parse objectmodel in DSF_Python?
-
Is there a built-in parser for the object_model in DSF_Ptyhon or is that on the developer? I can get it to return the entire object or split it at the top levels (boards, fans, job, limits, move, etc) but it won't return the value for nested objects.
If I'm wrong, will someone please post a sample on how to call specific nodes? Lets say I want to read object_model.job.file.fileName. Will it do that? Or do I need to read in obect_model.job.file and then parse out fileName?
Also, while global show up in the full object_model, I'm unable to get object_model.global. Is that by design?
The example I based this on is at https://github.com/Duet3D/dsf-python/blob/main/examples/subscribe_object_model.py
-
-
Without fail, I always seem to come up with a solution right after I decide to cast a net for some working examples.. I'd still like to understand why I can't load global.
#!/usr/bin/env python3 import json from dsf.connections import SubscribeConnection, SubscriptionMode def subscribe(): subscribe_connection = SubscribeConnection(SubscriptionMode.PATCH) subscribe_connection.connect() try: object_model = subscribe_connection.get_object_model() tVal = json.loads(str(object_model.job.file)) print(tVal["lastModified"]) finally: subscribe_connection.close() if __name__ == "__main__": subscribe()
This returns: 2023-10-31T14:32:34
-
@oozeBot
global
is a keyword in Python so it is replaced byglobals
: https://github.com/Duet3D/dsf-python/blob/main/src/dsf/object_model/object_model.py#L71 -
@Falcounet - This still isn't working for the global variables. See the example code below and the error it produces. Note that this code works when commenting out lines 22 & 23. Hopefully there is something simple I am doing wrong..
#!/usr/bin/env python3 """ Example of a subscribe connection to get the object model Make sure when running this script to have access to the DSF UNIX socket owned by the dsf user. """ import json from dsf.connections import SubscribeConnection, SubscriptionMode def subscribe(): subscribe_connection = SubscribeConnection(SubscriptionMode.PATCH) subscribe_connection.connect() try: # Get the complete model once object_model = subscribe_connection.get_object_model() tVal = json.loads( str( object_model.globals ) ) print( tVal["bedTemp"] ) tVal = json.loads( str( object_model.job ) ) print( tVal["filePosition"] ) tVal = json.loads( str( object_model.job.file ) ) print( tVal["fileName"] ) finally: subscribe_connection.close() if __name__ == "__main__": subscribe()
Traceback (most recent call last): File "/home/pi/./test.py", line 36, in <module> subscribe() File "/home/pi/./test.py", line 22, in subscribe tVal = json.loads( str( object_model.globals ) ) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
@oozeBot globals is a dictionary so you can't use str() on this.
Sorry the return type is missing for that property but that's seems pretty clear in the docstring.And no, there is nothing yet to get it back to the JSON format, you may have to do it yourself.
I suggest using a list comprehension over the dict elements with the String join() method. -
@Falcounet thank you. That's the nudge I needed and what I missed. Odd globals acts differently, but the following works by removing the json.loads. Thanks!
#!/usr/bin/env python3 """ Example of a subscribe connection to get the object model Make sure when running this script to have access to the DSF UNIX socket owned by the dsf user. """ import json from dsf.connections import SubscribeConnection, SubscriptionMode def subscribe(): subscribe_connection = SubscribeConnection(SubscriptionMode.PATCH) subscribe_connection.connect() try: # Get the complete model once object_model = subscribe_connection.get_object_model() tVal = object_model.globals print( tVal["bedTemp"] ) tVal = json.loads( str( object_model.job ) ) print( tVal["filePosition"] ) tVal = json.loads( str( object_model.job.file ) ) print( tVal["fileName"] ) finally: subscribe_connection.close() if __name__ == "__main__": subscribe()
-
-
@oozeBot I actually don't get why you are using the json ...
If you want to get the filename, you can get it usingobject_model.job.file.file_name
, same as filePosition :object_model.job.file_position
There is a little trick here the camelCase naming using by DSF is replaced by snake_casing as suggested by PEP8
-
@Falcounet said in Parse objectmodel in DSF_Python?:
There is a little trick here the camelCase naming using by DSF is replaced by snake_casing
Well.. I was using JSON to parse because I was unaware of this "trick" and this actually answers my original question/issue. Unfortunately for me, I am not a native Python developer (I'm a bit old-school - think Bash) and a lot of these "tricks" are not understood without working examples to build from.
With this in mind, I'll get back in the habit of posting more working examples to the forums for others to benefit from.
Thanks again
-
@oozeBot Yes I agree there is some lack of documentation ... and for now it mainly requires reading the code.
But on other hand, an IDE would suggest you the class attributes/properties and I believe the names are still pretty explicit.