--- 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)