Duet3D Logo Duet3D
    • Tags
    • Documentation
    • Order
    • Register
    • Login

    Q for @DC42 and Chris Hammacher

    Scheduled Pinned Locked Moved
    Beta Firmware
    7
    27
    1.6k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Danalundefined
      Danal
      last edited by

      In order to deal with only the socket, I'm going to send commands formatted like this:

      {"code":"M122 B1","channel":0,"command":"SimpleCode"}

      Delta / Kossel printer fanatic

      1 Reply Last reply Reply Quote 0
      • A Former User?
        A Former User @Danal
        last edited by

        @Danal said in Q for @DC42 and Chris Hammacher:

        they all run into the fact that CodeConsole closes stdin when it sees EOF.

        thats fair enough, but it shouldn't get an EOF before you call os.pclose() or g0Stream goes out of scope methinks. (although you clearly know more python than me, so I could be wrong, incorrect or all of the above)

        Danalundefined 1 Reply Last reply Reply Quote 0
        • Danalundefined
          Danal @A Former User
          last edited by

          @bearer said in Q for @DC42 and Chris Hammacher:

          @Danal said in Q for @DC42 and Chris Hammacher:

          they all run into the fact that CodeConsole closes stdin when it sees EOF.

          thats fair enough, but it shouldn't get an EOF before you call os.pclose() or g0Stream goes out of scope methinks. (although you clearly know more python than me, so I could be wrong, incorrect or all of the above)

          Yeah, you'd think. But whether invoked with any of several os.xxxx or fork, it ends after the first write to it's cloned stdin. I think python is set up so much to be nonblocking... maybe...

          Anyway, I'm off in socket land, and I like it a LOT better.

          Delta / Kossel printer fanatic

          1 Reply Last reply Reply Quote 0
          • Danalundefined
            Danal
            last edited by Danal

            Proof-of-concept level success in socketland. Decide to bypass the web socket and go straight to the control server's (internal) socket. This little program works:

            #!/usr/bin/env python3
            import socket
            import json
            import time
            
            s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
            s.connect('/var/run/dsf/dcs.sock')
            
            j=json.dumps({"mode":"command"})
            print(j)
            s.send(j.encode())
            time.sleep(0.002)
            r=s.recv(128)
            print(r.decode())
            
            j=json.dumps({"code": "M122 B1","channel": 0,"command": "SimpleCode"})
            print(j)
            s.send(j.encode())
            r=s.recv(128)
            print(r.decode())
            if (r.decode() == '{"success":true}'):
              r=s.recv(1024)
              print(r.decode())
            

            Delta / Kossel printer fanatic

            1 Reply Last reply Reply Quote 1
            • Danalundefined
              Danal
              last edited by Danal

              the 'dumps' or 'loads' turn python dictionaries to/from string-style-json

              the '.encode()' and matching dcode turn simple strings to/from "byte like objects", which are a python thing necessary for dealing with raw streams such as internal sockets.

              There is a bit of socket stream handling here and there, and then there is a bit of specific payloads and/or sequences that are Dave and Chris's way of talking to the control server. I figured those out from traces of what DWC was doing.

              Anyway, it should be possible to built the scripts I want to build on top of little wrappers for the above. Right this instant, my mind is fried and it is a VERY pretty day in North Texas. Going outside!!

              Delta / Kossel printer fanatic

              1 Reply Last reply Reply Quote 0
              • A Former User?
                A Former User
                last edited by

                Yeah, if the unix socket runs off json then why not.

                But CodeConsole runs fine with multiple commands through socat and across TCP (running my PanelDue now like so:) so its definitively a quirk with how its handled in Python; the only thing that strikes me is that it could be the echo cmd | bit that causes the issue with echo closing up its stdout causing CodeConsole to get the EOF right away? Anyway, the horse is dead, i'll stop beating it, or take a break at least:)

                Danalundefined 1 Reply Last reply Reply Quote 0
                • Danalundefined
                  Danal @A Former User
                  last edited by Danal

                  @bearer said in Q for @DC42 and Chris Hammacher:

                  Yeah, if the unix socket runs off json then why not.

                  But CodeConsole runs fine with multiple commands through socat and across TCP (running my PanelDue now like so:) so its definitively a quirk with how its handled in Python; the only thing that strikes me is that it could be the echo cmd | bit that causes the issue with echo closing up its stdout causing CodeConsole to get the EOF right away? Anyway, the horse is dead, i'll stop beating it, or take a break at least:)

                  I'm still kind of curious. Not the echo, that went away when I moved from shell to trying to keep a pipe open. Things like this. The first command M122 works, the second M114 hangs (stalls) forever. Tried LOTS of variants.

                  Anyway, like you said, horse, dead, beat, etc, etc.

                  rs, ws = os.pipe()
                  if not os.fork():
                    #child
                    os.dup(rs)    #stdin  to parent pipe
                    os.dup2(ws,1) #stdout to parent pipe
                    os.dup2(ws,2) #stderr to parent pipe
                    os.execv('/opt/dsf/bin/CodeConsole',['dummy'])
                    print('Failed to start CodeConsole')
                    sys.exit(8)
                  
                  #parent
                  wsf = os.fdopen(ws,'w')
                  rsf = os.fdopen(rs,'r')
                  
                  line = rsf.readline()
                  print(line)
                  if ('Connected!\n' != line):
                    print('Error connecting to DSF')
                    print(line)
                    for line in rsf:
                      print(line)
                    exit(8)
                  
                  
                  wsf.write('M122 B1\n')
                  line = rsf.readline()
                  print(line)
                  
                  wsf.write('M114\n')
                  for line in rsf:
                      print(line)
                  
                  

                  Delta / Kossel printer fanatic

                  1 Reply Last reply Reply Quote 0
                  • Danalundefined
                    Danal
                    last edited by Danal

                    And... here is a library based on the POC that can be imported into a Python program, with everything following the library being more-or-less straightforward gcode calls.

                    Only very lightly tested... and at least some of the sequence/race in the POC were wrong, so they could still be wrong here.

                    import socket
                    import json
                    
                    def openDSF():
                        s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
                        s.connect('/var/run/dsf/dcs.sock')
                        j=json.dumps({"mode":"command"}).encode()
                        s.send(j)
                        r=s.recv(128).decode()
                        if (-1 == r.find('{"version":')):
                              print("Failed to enter command mode - version not received")
                              print(r)
                              exit(8)
                        if (-1 == r.find('{"success":true}')):   #could be in same buffer as version
                            r=s.recv(128).decode()
                            if (-1 == r.find('{"success":true}')):
                                  print("Failed to enter command mode - success not received")
                                  print(r)
                                  exit(8)
                        return(s)
                    
                    def closeDSF(s):
                        s.close()
                    
                    def Gcode(s,cmd=''):
                        j=json.dumps({"code": cmd,"channel": 0,"command": "SimpleCode"}).encode()
                        s.send(j)
                        r=s.recv(2048).decode()
                        return(r)
                    
                    def getPos(s):
                      result = json.loads(Gcode(s,'M408'))['result']
                      pos = json.loads(result)['pos']
                      print('getPos = '+str(pos))
                      return pos
                    

                    Very short test:

                    #!/usr/bin/env python3
                    from DWClib import *
                    
                    DSFsock = openDSF()
                    
                    r=Gcode(DSFsock,'M114')
                    print(r)
                    print('====================================')
                    
                    r=Gcode(DSFsock,'M122 B1')
                    print(r)
                    print('====================================')
                    
                    r=Gcode(DSFsock,'M408')
                    print(json.loads(r))
                    print('====================================')
                    
                    p=getPos(DSFsock)
                    print(p[0])
                    
                    closeDSF(DSFsock)
                    

                    Delta / Kossel printer fanatic

                    A Former User? 1 Reply Last reply Reply Quote 2
                    • A Former User?
                      A Former User @Danal
                      last edited by A Former User

                      @Danal Nice, now how about using a proper language? (...while I go hide under my desk:)

                      ((My bad, that was just meant as praise with a sidedish of a poor joke; will poke it and see if it deals with M117, M118, M300 and other asyncronous stuff better than CodeConsole for mye PanelDue adventures. Thanks for doing the legwork!))

                      Danalundefined 1 Reply Last reply Reply Quote 0
                      • Danalundefined
                        Danal @A Former User
                        last edited by

                        @bearer said in Q for @DC42 and Chris Hammacher:

                        @Danal Nice, now how about using a proper language? (...while I go hide under my desk:)

                        Actually, I'm open to anything that's pre-installed on the Pi (and the Duet image, in particular), that leans even a little bit toward scripting.

                        What would you suggest?

                        Delta / Kossel printer fanatic

                        1 Reply Last reply Reply Quote 0
                        • gtj0undefined
                          gtj0
                          last edited by

                          Nice work @Danal !

                          1 Reply Last reply Reply Quote 0
                          • Danalundefined
                            Danal
                            last edited by

                            OK, switched to round hole. At this moment, hacked into the corner of the bed; for production would be more nicely integrated along an edge somewhere.

                            Also got the script working consistently. Based on 4 back-back runs, repeatability seems to be about 0.09mm in Z and 0.02 in X and Y. These are probably better than any hand method, and usable for printing. At the same time, I'd like for them to be even more consistent and may tweak a few things.

                            IMG_0169.jpeg

                            Delta / Kossel printer fanatic

                            timothyzundefined 1 Reply Last reply Reply Quote 0
                            • timothyzundefined
                              timothyz @Danal
                              last edited by

                              @Danal .09mm in Z repeatability seems rather high, and I would expect that to be much lower than the xy repeatability. Any thoughts as to why this is?

                              Danalundefined 1 Reply Last reply Reply Quote 0
                              • Danalundefined
                                Danal @timothyz
                                last edited by

                                @timothyz said in Q for @DC42 and Chris Hammacher:

                                @Danal .09mm in Z repeatability seems rather high, and I would expect that to be much lower than the xy repeatability. Any thoughts as to why this is?

                                Yeah, I was concerned about that as well. Not sure.

                                I need to literally "look" at the printer while this runs. Or single steps. With a dial gauge or similar.

                                And/or, even at feedrate F100, I may back off slightly and retouch at an even lower feedrate.

                                Delta / Kossel printer fanatic

                                1 Reply Last reply Reply Quote 0
                                • Danalundefined
                                  Danal
                                  last edited by

                                  Also, I've cleaned up a bunch of things, and published this all on github.

                                  And... started a new thread. So Dave and Chris don't have to see the title of this one keep popping up!

                                  Delta / Kossel printer fanatic

                                  1 Reply Last reply Reply Quote 0
                                  • wilrikerundefined
                                    wilriker
                                    last edited by

                                    Just for the sake of completeness: there does not yet exist an official python library to the DuetAPI (but it is on the roadmap - next I think). There exists of course the C#.NET library that e.g. CodeConsole is built upon as well as my Go library (https://github.com/wilriker/goduetapiclient).

                                    And this wraps up that there is no current (full) client library for any scripting language. Thus great job at getting started @Danal! 👍

                                    Manuel
                                    Duet 3 6HC (v0.6) with RPi 4B on a custom Cartesian
                                    with probably always latest firmware/DWC (incl. betas or self-compiled)
                                    My Tool Collection

                                    1 Reply Last reply Reply Quote 0
                                    • First post
                                      Last post
                                    Unless otherwise noted, all forum content is licensed under CC-BY-SA