Wie erhält man die Position eines Objekts im Projektbaum

tinogoetz
2011-05-06
2011-05-09
  • tinogoetz - 2011-05-06

    Schön, dass es jetzt auch mit Python möglich CoDeSys-Projekte zu manipulieren.

    Für unseren Systemtest, bei dem eine CoDeSys-Steuerung über EtherCAT mit den Feldgeräten kommuniziert
    müssen wir verschiedene Geräteszenarien durchspielen, bei denen nur die Reihenfolge der Geräte unter dem EtherCAT-Master verändert wird.

    Über

    \# coding=utf-8
     from __future__ import print_function
     ecatmaster=proj.find("EtherCAT_Master",True)[0]
      for dev in ecatmaster.get_children():
        print(dev.get_name()) [/color]
    

    bekommt man alle Feldgeräte gelistet.

    Nachdem ich mir das Ergebnis vom print() angeschaut habe, viel mir jedoch auf, das die Objekte nicht in der Reihenfolge gelistet werden, wie sie unter dem EtherCAT_Master angeordnet waren, sondern in der zeitlichen Reihenfolge des Einfügens also mit aufsteigender Object-ID . (Wenn man die Gerätereihenfolge mit der Maus verändert, ändert dies z.B. nichts an der Ausgabe-Reihenfolge des prints)

    Meine Frage lautet daher: Ist es möglich auch an die Position der Slaves unter dem Master heranzukommen, da dies bei EtherCat auch einen physikalischen Bezug hat.
    -> EtherCAT-NodeID = Position+1000

    PS: Anbei auch das weitere Vorgehen um Projektvarianten zu erzeugen bei denen alle Geräte unterhalb des Master_Knotens von Projekt zu Projekt ringförmig geshiftet werden -> Script im Anhang

    Wenn die Geräte bekannt sind kann man mit Hilfe der XmlExport- und XmlImportfunktion das Projekt so manipulieren, dass die Geräte in anderer Reihenfolge unter dem Master angeordnet werden.
    Die referenzierte Variablen vom I/O Abbild bleiben dabei erhalten, so das sich nur die Reihenfolge, nicht aber die Funktion der Geräte ändert.

    Hinweis, die im Skript implementierten Reportklassen müssen sein, damit die Import und Exportmethoden genutzt werden können.

    \# coding=utf-8
    from __future__ import print_function
    import sys
    import os
    \# name of project must be name of script
    \# result are written in <
    pathscript = os.path.splitext(__file__)[0] # unser script
    pathproject = pathscript
    pathresult = pathscript
    \# objectname in project of ethercat master must be "EtherCAT_Master"
    ecatmaster_name="EtherCAT_Master"
    \# redirect prints 
    sys.stdout = open(pathresult+".txt","w") 
      
    class exrep(ExportReporter):
      def  error(self):
        print("error")
      def nonexportable(self):
        print("nonexportable")
      def warning(self):
        print("warning")
      def get_aborting(self):
         return False
    class imrep(ImportReporter):  
      def added():
        print("added")
      def error(self):
        print("error")
      def replaced():
        print("replaced")
      def resolve_conflict(self):
        print("resolve_conflict")
      def skipped(self):
        print("skipped")
      def warning(self):
        print("warning")
      def get_aborting(self):
        return False
    try:
      
      proj = projects.open(pathproject+'.project')
      print(pathscript)
      
      ecatmaster=proj.find(ecatmaster_name,True)[0]
      
      devs=ecatmaster.get_children()
      for dev in devs:
        print(dev.get_name())
        
      # export devices
      exreporter=exrep();
      devxml=[];
      for dev in devs:
        devxml.append(pathproject+"_%s.xml"%dev.get_name())
        proj.export_xml(exreporter,[dev],devxml[-1],recursive=True)
      # define all variants of project by rotation of devices
      chain=range(1,len(devs)+1)
      per=[]
      for n in chain:
        per.append(chain)
        chain=chain[1:]+chain[:1]
      # create project variants
      imreporter=imrep();
      for chain in per:
        # first clear devices
        for dev in ecatmaster.get_children():
          dev.remove()
        # import devices in order of chain
        for n in chain:      
          ecatmaster.import_xml(imreporter,devxml[n-1])    
        
        proj.save_as(pathproject+"_var%02u.project"%chain[0])
        print("saved variant: %s" % chain)
    except Exception, e:
      print(e)      
    sys.stdout.close()
    proj.close()
    \#system.exit()
    
     

    Related

    Talk.ru: 1

  • Anonymous - 2011-05-09

    Originally created by: M.Schaber

    Hallo, Tino,

    tinogoetz hat geschrieben:
    -> Die bei python so wichtigen Einrückungen gehen in diesem Forum leider verloren
    Anfangsleerzeichen werden gelöscht, Mehrfachleerzeichen durch einzelne ersetzt, Dateinahänge mit .py oder .txt wurden nicht akzeptiert.

    http://forum.3s-software.com/viewtopic.php?p=11487#p11487.

    tinogoetz hat geschrieben:
    Nachdem ich mir das Ergebnis vom print() angeschaut habe, viel mir jedoch auf, das die Objekte nicht in der Reihenfolge gelistet werden, wie sie unter dem EtherCAT_Master angeordnet waren, sondern in der zeitlichen Reihenfolge des Einfügens also mit aufsteigender Object-ID . (Wenn man die Gerätereihenfolge mit der Maus verändert, ändert dies z.B. nichts an der Ausgabe-Reihenfolge des prints)
    Meine Frage lautet daher: Ist es möglich auch an die Position der Slaves unter dem Master heranzukommen, da dies bei EtherCat auch einen physikalischen Bezug hat.
    -> EtherCAT-NodeID = Position+1000

    Die Gerätereihenfolge kannst Du vielleicht rauskriegen, in dem Du nach dem index-Property sortierst. Das müsste in diesen Fällen die Reihenfolge angeben.

    tinogoetz hat geschrieben:
    PS: Anbei auch das weitere Vorgehen um Projektvarianten zu erzeugen bei denen alle Geräte unterhalb des Master_Knotens von Projekt zu Projekt ringförmig geshiftet werden -> Script im Anhang
    Wenn die Geräte bekannt sind kann man mit Hilfe der XmlExport- und XmlImportfunktion das Projekt so manipulieren, dass die Geräte in anderer Reihenfolge unter dem Master angeordnet werden.
    Die referenzierte Variablen vom I/O Abbild bleiben dabei erhalten, so das sich nur die Reihenfolge, nicht aber die Funktion der Geräte ändert.

    Wunderbar, danke für das Beispielskript. Vielleicht würde in diesem Falle auch die move()-Methode weiterhelfen, der kannst Du auch einen Index angeben.

    tinogoetz hat geschrieben:
    Hinweis, die im Skript implementierten Reportklassen müssen sein, damit die Import und Exportmethoden genutzt werden können.

    Dafür haben wir schon eine Verbesserung in der Schublade, allerdings gibt es noch kein geplantes Release-Datum.

     
  • tinogoetz - 2011-05-09

    Der Hinweis mit dem property index hat prima geklappt.
    ebenso der mit dem code-Format (Anfängerfehler)

    Anbei die Ergänzung für die Sortierung und deren Ausgabe

      ecatmaster_name="EtherCAT_Master"
      ecatmaster=proj.find(ecatmaster_name,True)[0]
      devs=sorted(ecatmaster.get_children(), key = lambda dev: dev.index)
      for dev in devs:
        print(" %02u %s"%(dev.index, dev.get_name()))      
    

    Der Hinweis mit der move-Methode führte jedoch nicht zum Ziel.
    Ich bekam die Fehlermeldung, dass man dort nicht hinschieben könne.
    weder mit:

    devs[0].move(ecatmaster, len(devs)) # verdrängung des letzten devices?
    noch mit:
    devs[0].move(ecatmaster, len(devs)+1)

    deshalb funktioniert mein Skript weiter über xml-export und xml-import

    \# coding=utf-8
    from __future__ import print_function
    import sys
    import os
    \# names of script, project and logfile may be different
    pathscript = os.path.splitext(__file__)[0] # unser script
    pathproject= pathscript
    pathlog = pathscript
    \# objectname in project of ethercat master
    ecatmaster_name="EtherCAT_Master"
    \# redirect prints 
    sys.stdout = open(pathlog+".txt","w") 
      
    class exrep(ExportReporter):
      def  error(self):
        print("error")
      def nonexportable(self):
        print("nonexportable")
      def warning(self):
        print("warning")
      def get_aborting(self):
         return False
    class imrep(ImportReporter):  
      def added():
        print("added")
      def error(self):
        print("error")
      def replaced():
        print("replaced")
      def resolve_conflict(self):
        print("resolve_conflict")
      def skipped(self):
        print("skipped")
      def warning(self):
        print("warning")
      def get_aborting(self):
        return False
    try:  
      proj = projects.open(pathproject+'.project')
      ecatmaster=proj.find(ecatmaster_name,True)[0]
      devs=sorted(ecatmaster.get_children(), key = lambda dev: dev.index)
      
      # log configuration
      print("source project: %s.project"%pathproject)
      print("export from %s"%ecatmaster_name)  
      for dev in devs:
        print(" %02u %s"%(dev.index, dev.get_name()))      
         
      # export devices
      exreporter=exrep()
      devxml=[];
      for dev in devs:
        devxml.append(pathscript+dev.get_name()+".xml")
        proj.export_xml(exreporter,[dev],devxml[-1],recursive=True)
      # define all variants of project by rotation of devices
      chain=range(1,len(devs)+1)
      per=[]
      for n in chain:
        per.append(chain)
        chain=chain[1:]+chain[:1]
      # create project variants
      imreporter=imrep()
      for chain in per:
        # first clear devices        
        for dev in devs:
          dev.remove()
        
        # import devices in order of chain
        for n in chain:      
          ecatmaster.import_xml(imreporter,devxml[n-1])    
        
        # save variant
        dest_fullname=pathproject+"_var%02u.project"%chain[0]
        proj.save_as(dest_fullname)
        
        # log configuration 
        print("import to %s"%ecatmaster_name)        
        devs=sorted(ecatmaster.get_children(), key = lambda dev: dev.index)    
        for dev in devs:
          print(" %02u %s"%(dev.index, dev.get_name()))      
        print("saved variant: %s" % chain)
        print("destination project: %s"%dest_fullname)
            
    except Exception, e:
      print(e)      
    sys.stdout.close()
    proj.close()
    \#system.exit()
    
     

    Related

    Talk.ru: 1


Log in to post a comment.