etherlab/etherlab.py
branchethercat_from_kosmos
changeset 2641 c9deff128c37
parent 2165 02a2b5dee5e3
child 2643 b98d9e08231f
--- a/etherlab/etherlab.py	Sat Jun 23 09:17:20 2018 +0200
+++ b/etherlab/etherlab.py	Wed Nov 20 16:57:15 2019 +0100
@@ -10,6 +10,8 @@
 # See COPYING file for copyrights details.
 
 import os, shutil
+
+#from xml.dom import minidom
 from lxml import etree
 
 import wx
@@ -33,13 +35,16 @@
 EtherCATInfoParser = GenerateParserFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATInfo.xsd")) 
 EtherCATInfo_XPath = lambda xpath: etree.XPath(xpath)
 
+EtherCATBaseParser = GenerateParserFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATBase.xsd"))
+EtherCATBase_XPath = lambda xpath1: etree.XPath(xpath1)
+
 def HexDecValue(context, *args):
     return str(ExtractHexDecValue(args[0][0]))
 
 def EntryName(context, *args):
     return ExtractName(args[0], 
         args[1][0] if len(args) > 1 else None)
-
+        
 ENTRY_INFOS_KEYS = [
     ("Index", lambda x: "#x%4.4X" % int(x), "#x0000"),
     ("SubIndex", str, "0"),
@@ -52,6 +57,19 @@
     ("PDO name", str, ""),
     ("PDO type", str, "")]
 
+# Read DefaultValue from ESI file
+# Add by jblee 151229
+ENTRY_INFOS_KEYS_FOR_DV = [
+    ("Index", lambda x: "#x%4.4X" % int(x), "#x0000"),
+    ("SubIndex", str, "0"),
+    ("Name", str, ""),
+    ("Type", str, ""),
+    ("BitSize", int, 0),
+    ("Access", str, ""),
+    ("PDOMapping", str, ""),
+    ("DefaultValue", str, ""),
+    ("Sub_entry_flag", str, "0")]
+
 class EntryListFactory:
 
     def __init__(self, entries):
@@ -59,11 +77,17 @@
     
     def AddEntry(self, context, *args):
         index, subindex = map(lambda x: int(x[0]), args[:2])
-        new_entry_infos = {
+        if len(args) > 9:
+		    new_entry_infos = {
             key: translate(arg[0]) if len(arg) > 0 else default
             for (key, translate, default), arg
             in zip(ENTRY_INFOS_KEYS, args)}
-        
+        else:
+            new_entry_infos = {
+            key: translate(arg[0]) if len(arg) > 0 else default
+            for (key, translate, default), arg
+            in zip(ENTRY_INFOS_KEYS_FOR_DV, args)}			
+			
         if (index, subindex) != (0, 0):
             entry_infos = self.Entries.get((index, subindex))
             if entry_infos is not None:
@@ -79,6 +103,7 @@
 
 cls = EtherCATInfoParser.GetElementClass("DeviceType")
 if cls:
+    cls.DataTypes = None
     
     profile_numbers_xpath = EtherCATInfo_XPath("Profile/ProfileNo")
     def GetProfileNumbers(self):
@@ -92,25 +117,151 @@
         return None
     setattr(cls, "getCoE", getCoE)
 
+    # Modify by jblee
+    def ExtractDataTypes(self):
+        #self.DataTypes = {}
+        #self.DT = {}
+        DT = {}
+        objects = []
+
+        # get Profile Field
+        for profile in self.getProfile():
+            # get each (ProfileNo, Dictionary) Field as child
+            for child in profile.getchildren():
+                # child.text is not None -> ProfileNo, is None -> Dictionary
+                if child.text is None:
+                    # get each (DataTypes, Objects) Field 
+                    dataTypes = child.getDataTypes()
+                    objects = child.getObjects()
+                                
+                    for dataType in dataTypes.getDataType():
+                        #if dataType.getName() is not None:
+                        #    print dataType.getName(), dataType
+                        DT[dataType.getName()] = dataType
+
+        return DT, objects
+    setattr(cls, "ExtractDataTypes", ExtractDataTypes)
+
     def GetEntriesList(self, limits=None):
+        DataTypes, objects = self.ExtractDataTypes()
+
         entries = {}
-        
-        factory = EntryListFactory(entries)
-        
-        entries_list_xslt_tree = etree.XSLT(
-            entries_list_xslt, extensions = {
-                ("entries_list_ns", "AddEntry"): factory.AddEntry,
-                ("entries_list_ns", "HexDecValue"): HexDecValue,
-                ("entries_list_ns", "EntryName"): EntryName})
-        entries_list_xslt_tree(self, **dict(zip(
-            ["min_index", "max_index"], 
-            map(lambda x: etree.XSLT.strparam(str(x)),
-                limits if limits is not None else [0x0000, 0xFFFF])
-            )))
+
+        # get each Object Field
+        for object in objects:
+            # Object Field mendatory : Index, Name, Type, BitSize
+            # Frequently Use : Info, Flags
+            # Info Field -> DefaultData, SubItem
+            # Flags Field -> Access, Category, PdoMapping
+            object_index = object.getIndex().getcontent()
+            index = ExtractHexDecValue(object_index)
+            if limits is None or limits[0] <= index <= limits[1]:
+                object_type = object.getType()
+                object_name = ExtractName(object.getName())
+                object_size = object.getBitSize()
+                defaultData = ""
+                object_access = ""
+                object_PDOMapping_data = ""
+
+                object_type_infos = DataTypes.get(object_type, None)
+                subItem_infos = object_type_infos.getchildren()
+                countSubIndex = 0
+                if len(subItem_infos) > 2:
+                    for subItem_info in subItem_infos:
+                        if subItem_info.tag == "SubItem" : 
+                            subItemName = subItem_info.getName()
+                            subIdx = subItem_info.getSubIdx()
+                            if subIdx is not None:
+                                object_subidx = ExtractHexDecValue(subIdx)
+                            else:
+                                object_subidx = ExtractHexDecValue(countSubIndex)
+                            subType = subItem_info.getType()
+                            subBitSize = subItem_info.getBitSize()
+                            subFlags = subItem_info.getFlags()
+                            subAccess = ""
+                            subPDOMapping_data = ""
+                            if subFlags is not None:
+                                subAccess = subFlags.getAccess().getcontent()
+                                subPDOMapping = subFlags.getPdoMapping()                                                        
+                                if subPDOMapping is not None:
+                                    subPDOMapping_data = subFlags.getPdoMapping().upper()
+
+                            entries[(index, object_subidx)] = {
+                                "Index": object_index,
+                                "SubIndex": subIdx,
+                                "Name": "%s - %s" % 
+                                    (object_name.decode("utf-8"),
+                                     subItemName.decode("utf-8")),
+                                "Type": subType,
+                                "BitSize": subBitSize,
+                                "Access": subAccess, 
+                                "PDOMapping": subPDOMapping_data}
+
+                            countSubIndex += 1
+
+                    info = object.getInfo()
+                    # subItemTest : check subItem 
+                    countSubIndex = 0
+                    if info is not None:
+                        subItems = info.getchildren()
+                        if len(subItems) > 1:
+                            for subItem in subItems:
+                                defaultdata_subidx = ExtractHexDecValue(countSubIndex)
+                                defaultData = subItem.getchildren()[1].findtext("DefaultData")
+                                entry = entries.get((index, defaultdata_subidx), None)
+                                if entry is not None:
+                                    entry["DefaultData"] = defaultData
+                                countSubIndex += 1
+
+                else :
+                    info = object.getInfo()
+                    if info is not None:
+                        subItems = info.getchildren()
+                        if len(subItems) <= 1:
+                            defaultData = subItems[0].text
+                                
+                    object_flag = object.getFlags()
+                    object_access = object_flag.getAccess().getcontent()
+                    object_PDOMapping = object_flag.getPdoMapping()
+                    if object_PDOMapping is not None:
+                        object_PDOMapping_data = object_flag.getPdoMapping().upper()
+                    entries[(index, 0)] = {
+                        "Index": object_index,
+                        "SubIndex": "0",
+                        "Name": object_name,                                                               
+                        "Type": object_type,
+                        "BitSize": object_size,
+                        "DefaultData" : defaultData,
+                        "Access": object_access, 
+                        "PDOMapping": object_PDOMapping_data}
+
+        for TxPdo in self.getTxPdo():
+            ExtractPdoInfos(TxPdo, "Transmit", entries, limits)
+        for RxPdo in self.getRxPdo():
+            ExtractPdoInfos(RxPdo, "Receive", entries, limits)
         
         return entries
     setattr(cls, "GetEntriesList", GetEntriesList)
 
+#    def GetEntriesList(self, limits=None):
+#        entries = {}
+        
+#        factory = EntryListFactory(entries)
+        
+#        entries_list_xslt_tree = etree.XSLT(
+#            entries_list_xslt, extensions = {
+#                ("entries_list_ns", "AddEntry"): factory.AddEntry,
+#                ("entries_list_ns", "HexDecValue"): HexDecValue,
+#                ("entries_list_ns", "EntryName"): EntryName})
+#        entries_list_xslt_tree(self, **dict(zip(
+#            ["min_index", "max_index"], 
+#            map(lambda x: etree.XSLT.strparam(str(x)),
+#                limits if limits is not None else [0x0000, 0xFFFF])
+#            )))
+#        
+#        return entries
+#    setattr(cls, "GetEntriesList", GetEntriesList)
+
     def GetSyncManagers(self):
         sync_managers = []
         for sync_manager in self.getSm():
@@ -127,6 +278,8 @@
         return sync_managers
     setattr(cls, "GetSyncManagers", GetSyncManagers)
 
+cls2 = EtherCATInfoParser.GetElementClass("DeviceType")
+
 def GroupItemCompare(x, y):
     if x["type"] == y["type"]:
         if x["type"] == ETHERCAT_GROUP:
@@ -143,6 +296,50 @@
             SortGroupItems(item)
     group["children"].sort(GroupItemCompare)
 
+def ExtractPdoInfos(pdo, pdo_type, entries, limits=None):
+    pdo_index = pdo.getIndex().getcontent()
+    pdo_name = ExtractName(pdo.getName())
+    exclude = pdo.getExclude()
+    for pdo_entry in pdo.getEntry():
+        entry_index = pdo_entry.getIndex().getcontent()
+        entry_subindex = pdo_entry.getSubIndex()
+        index = ExtractHexDecValue(entry_index)
+        subindex = ExtractHexDecValue(entry_subindex)
+        object_size = pdo_entry.getBitLen()
+
+        if limits is None or limits[0] <= index <= limits[1]:
+            entry = entries.get((index, subindex), None)
+            if entry is not None:
+                entry["PDO index"] = pdo_index
+                entry["PDO name"] = pdo_name
+                entry["PDO type"] = pdo_type
+            else:
+                entry_type = pdo_entry.getDataType()
+                if entry_type is not None:
+                    if pdo_type == "Transmit":
+                        access = "ro"
+                        pdomapping = "T"
+                    else:
+                        access = "wo"
+                        pdomapping = "R"
+                    entries[(index, subindex)] = {
+                        "Index": entry_index,
+                        "SubIndex": entry_subindex,
+                        "Name": ExtractName(pdo_entry.getName()),
+                        "Type": entry_type.getcontent(),
+                        "BitSize": object_size,
+                        "Access": access,
+                        "PDOMapping": pdomapping}
+
+#cls3 = EtherCATBaseParser.GetElementClass("ModuleType")
+#if cls3:
+#    module_xpath = EtherCATBase_XPath("Descriptions/Modules/Module")
+#    def test(self):
+#        print module_xpath
+
+#    setattr(cls, "test", test)
+
+
 class ModulesLibrary:
 
     MODULES_EXTRA_PARAMS = [
@@ -180,7 +377,7 @@
         else:
             self.Library = None
         self.LoadModulesExtraParams()
-    
+
     def GetPath(self):
         return self.Path
     
@@ -189,8 +386,20 @@
     
     groups_xpath = EtherCATInfo_XPath("Descriptions/Groups/Group")
     devices_xpath = EtherCATInfo_XPath("Descriptions/Devices/Device")
+    module_xpath = EtherCATBase_XPath("Descriptions/Modules/Module")
+
     def LoadModules(self):
         self.Library = {}
+        # add by jblee for Modular Device Profile
+        self.MDPList = []
+        self.ModuleList = []
+        self.MDPEntryList = {}
+        dtDic = {}
+        self.idxIncrement = 0
+        self.slotIncrement = 0
+        # add by jblee for PDO Mapping
+        self.DataTypes = {}
+        self.ObjectDictionary = {}
         
         files = os.listdir(self.Path)
         for file in files:
@@ -201,13 +410,13 @@
                 xmlfile = open(filepath, 'r')
                 try:
                     self.modules_infos, error = EtherCATInfoParser.LoadXMLString(xmlfile.read())
-                    if error is not None:
-                        self.GetCTRoot().logger.write_warning(
-                            XSDSchemaErrorMessage % (filepath + error))
+                    #if error is not None:
+                    #    self.GetCTRoot().logger.write_warning(
+                    #        XSDSchemaErrorMessage % (filepath + error))
                 except Exception, exc:
                     self.modules_infos, error = None, unicode(exc)
                 xmlfile.close()
-                
+
                 if self.modules_infos is not None:
                     vendor = self.modules_infos.getVendor()
                     
@@ -218,13 +427,17 @@
                     
                     for group in self.groups_xpath(self.modules_infos):
                         group_type = group.getType()
+                        # add for XmlToEeprom Func by jblee.
+                        self.LcId_data = group.getchildren()[1]
+                        self.Image16x14_data = group.getchildren()[2]
                         
                         vendor_category["groups"].setdefault(group_type, 
                             {"name": ExtractName(group.getName(), group_type), 
                              "parent": group.getParentGroup(),
                              "order": group.getSortOrder(), 
-                             #"value": group.getcontent()["value"],
-                             "devices": []})
+                             "devices": [],
+                            # add jblee for support Moduler Device Profile (MDP)
+                             "modules": []})
                     
                     for device in self.devices_xpath(self.modules_infos):
                         device_group = device.getGroupType()
@@ -232,14 +445,101 @@
                             raise ValueError, "Not such group \"%\"" % device_group
                         vendor_category["groups"][device_group]["devices"].append(
                             (device.getType().getcontent(), device))
-                
+
+                        # ------------------ Test Section --------------------#
+                        slots = device.getSlots()
+                        if slots is not None:
+                            for slot in slots.getSlot():
+                                self.idxIncrement = slot.getSlotIndexIncrement()
+                                self.slotIncrement = slot.getSlotPdoIncrement()
+                                for child in slot.getchildren():
+                                    if child.tag == "ModuleClass":
+                                        child_class = child.getClass()
+                                        child_name = child.getName()
+
+                    # -------------------- Test Section ----------------------------------# 
+                        LocalMDPList = []
+                        for module in self.module_xpath(self.modules_infos):
+                            module_type = module.getType().getModuleClass()
+                            module_name = module.getName()
+                            LocalMDPData = ExtractName(module_name) + " (" + module_type + ")"
+                            
+                            self.ModuleList.append(module)
+                            try :
+                                module_pdos = module.getTxPdo()
+                                module_pdos += module.getRxPdo()
+                                for module_pdo in module_pdos:
+                                    device_name = ExtractName(module_name)
+                                    pdo_index = module_pdo.getIndex().getcontent()
+                                    pdo_name = ExtractName(module_pdo.getName())
+                                    pdo_entry = module_pdo.getEntry()
+                                    if module_pdo.tag == "TxPdo":
+                                        mapping_type = "T"
+                                    else :
+                                        mapping_type = "R"
+
+                                    LocalMDPEntry = []
+                                    for entry in pdo_entry:
+                                        entry_index = entry.getIndex().getcontent()
+                                        entry_subidx = entry.getSubIndex()
+                                        entry_name = ExtractName(entry.getName())
+                                        entry_bitsize = entry.getBitLen()
+                                        try :
+                                           entry_type = entry.getDataType().getcontent()
+                                        except :
+                                           entry_type = ""
+
+                                        LocalMDPEntry.append({
+                                            "Index": entry_index,
+                                            "SubIndex": entry_subidx,
+                                            "Name": "%s - %s" % (pdo_name, entry_name),
+                                            "Type": entry_type,
+                                            "BitSize": entry_bitsize,
+                                            "Access": "", 
+                                            "PDOMapping": mapping_type})
+                                
+                                    self.MDPEntryList[device_name] = LocalMDPEntry
+
+                                LocalMDPList.append([LocalMDPData, module, LocalMDPEntry])
+                            except :
+                                LocalMDPList.append([LocalMDPData, module, []])
+                           
+                        if LocalMDPList:
+                            vendor_category["groups"][device_group]["modules"].append(
+                                (device.getType().getcontent(), LocalMDPList, self.idxIncrement, self.slotIncrement))
+                            #self.MDPList.append([device.getType().getcontent(), LocalMDPList,
+                            #                     self.idxIncrement, self.slotIncrement])
+
+                    # --------------------------------------------------------------------- #
+
                 else:
-                        
-                    self.GetCTRoot().logger.write_error(
-                        _("Couldn't load %s XML file:\n%s") % (filepath, error))
-                
-        return self.Library
-
+                    pass                      
+                    #self.GetCTRoot().logger.write_error(
+                    #    _("Couldn't load %s XML file:\n%s") % (filepath, error))
+
+        #print self.ObjectDictionary
+        return self.Library ## add jblee
+
+    # add jblee
+    def GetMDPList(self):
+        return self.MDPList
+
+    # add jblee
+    def GetSelectModule(self, idx):
+        return self.ModuleList[idx]
+
+    # add jblee
+    def GetModuleEntryList(self):
+        return self.MDPEntryList
+
+    # add jblee
+    def GetModuleIncrement(self):
+        return (self.idxIncrement, self.slotIncrement)
+
+    # add jblee
+    #def GetEntriesList(self):
+    #    return self.ObjectDictionary
+    
     def GetModulesLibrary(self, profile_filter=None):
         if self.Library is None:
             self.LoadModules()
@@ -301,10 +601,22 @@
                     revision_number = ExtractHexDecValue(device_infos.getType().getRevisionNo())
                     if (product_code == ExtractHexDecValue(module_infos["product_code"]) and
                         revision_number == ExtractHexDecValue(module_infos["revision_number"])):
-                        self.cntdevice = device_infos 
-                        self.cntdeviceType = device_type  
+                        self.cntdevice = device_infos ## add by hwang 13.05.01.
+                        self.cntdeviceType = device_type  ## add by hwang 13.05.01.
                         return device_infos, self.GetModuleExtraParams(vendor, product_code, revision_number)
         return None, None
+
+    # add jblee for MDP
+    def GetMDPInfos(self, module_infos):
+        vendor = ExtractHexDecValue(module_infos["vendor"])
+        vendor_infos = self.Library.get(vendor)
+        if vendor_infos is not None:
+            for group_name, group_infos in vendor_infos["groups"].iteritems():
+                return group_infos["modules"]
+                #for device_type, module_list, idx_inc, slot_inc in group_infos["modules"]:
+                #    return module_list, idx_inc, slot_inc
+
+        #return None, None, None
     
     def ImportModuleLibrary(self, filepath):
         if os.path.isfile(filepath):
@@ -387,7 +699,6 @@
     
     CTNChildrenTypes = [("EthercatNode",_EthercatCTN,"Ethercat Master")]
     EditorType = LibraryEditor
-       
     
     def __init__(self):
         self.ModulesLibrary = None
@@ -424,10 +735,32 @@
     
     def GetModulesLibrary(self, profile_filter=None):
         return self.ModulesLibrary.GetModulesLibrary(profile_filter)
-    
+
+    # add jblee
+    def GetMDPList(self):
+        return self.ModulesLibrary.GetMDPList()
+
+    # add jblee
+    def GetSelectModule(self, idx):
+        return self.ModulesLibrary.GetSelectModule(idx)
+
+    # add jblee
+    def GetModuleEntryList(self):
+        return self.ModulesLibrary.GetModuleEntryList()
+
+    # add jblee
+    def GetModuleIncrement(self):
+        return self.ModulesLibrary.GetModuleIncrement()
+
+    # add jblee
+    #def GetEntriesList(self, limits = None):
+    #    return self.ModulesLibrary.GetEntriesList()
+
     def GetVendors(self):
         return self.ModulesLibrary.GetVendors()
     
     def GetModuleInfos(self, module_infos):
         return self.ModulesLibrary.GetModuleInfos(module_infos)
 
+    def GetMDPInfos(self, module_infos):
+        return self.ModulesLibrary.GetMDPInfos(module_infos)