--- a/etherlab/CommonEtherCATFunction.py Wed Nov 13 11:21:04 2019 +0100
+++ b/etherlab/CommonEtherCATFunction.py Mon Nov 25 08:10:45 2019 +0100
@@ -50,10 +50,9 @@
return name.getcontent()
return default
-# --------------------------------------------------
+#--------------------------------------------------
# Remote Exec Etherlab Commands
-# --------------------------------------------------
-
+#--------------------------------------------------
# --------------------- for master ---------------------------
MASTER_STATE = """
@@ -84,18 +83,21 @@
returnVal = result
"""
-# ethercat sdos -p (slave position)
-SLAVE_SDO = """
+# ethercat upload -p (slave position) -t (type) (index) (sub index)
+SDO_UPLOAD = """
import commands
-result = commands.getoutput("ethercat sdos -p %d")
-returnVal =result
-"""
-
-# ethercat upload -p (slave position) (main index) (sub index)
-GET_SLOW_SDO = """
-import commands
-result = commands.getoutput("ethercat upload -p %d %s %s")
-returnVal =result
+sdo_data = []
+input_data = "%s"
+slave_pos = %d
+command_string = ""
+for sdo_token in input_data.split(","):
+ if len(sdo_token) > 1:
+ sdo_token = sdo_token.strip()
+ type, idx, subidx = sdo_token.split(" ")
+ command_string = "ethercat upload -p " + str(slave_pos) + " -t " + type + " " + idx + " " + subidx
+ result = commands.getoutput(command_string)
+ sdo_data.append(result)
+returnVal =sdo_data
"""
# ethercat download -p (slave position) (main index) (sub index) (value)
@@ -119,6 +121,25 @@
returnVal =result
"""
+# ethercat reg_read -p (slave position) (address) (size)
+MULTI_REG_READ = """
+import commands
+output = []
+addr, size = range(2)
+slave_num = %d
+reg_info_str = "%s"
+reg_info_list = reg_info_str.split("|")
+for slave_idx in range(slave_num):
+ for reg_info in reg_info_list:
+ param = reg_info.split(",")
+ result = commands.getoutput("ethercat reg_read -p "
+ + str(slave_idx) + " "
+ + param[addr] + " "
+ + param[size])
+ output.append(str(slave_idx) + "," + param[addr] + "," + result)
+returnVal = output
+"""
+
# ethercat sii_write -p (slave position) - (contents)
SII_WRITE = """
import subprocess
@@ -143,6 +164,12 @@
returnVal =result
"""
+# ethercat pdos
+PDOS = """
+import commands
+result = commands.getoutput("ethercat pdos -p 0")
+returnVal =result
+"""
# --------------------------------------------------
# Common Method For EtherCAT Management
@@ -152,14 +179,40 @@
# ----- Data Structure for ethercat management ----
SlaveState = ""
+ # SDO base data type for Ethercatmaster
+ BaseDataTypes = {
+ "bool": ["BOOLEAN", "BOOL", "BIT"],
+ "uint8": ["BYTE", "USINT", "BIT1", "BIT2", "BIT3", "BIT4", "BIT5", "BIT6",
+ "BIT7", "BIT8", "BITARR8", "UNSIGNED8"],
+ "uint16": ["BITARR16", "UNSIGNED16", "UINT"],
+ "uint32": ["BITARR32", "UNSIGNED24", "UINT24", "UNSIGNED32", "UDINT"],
+ "uint64": ["UNSINED40", "UINT40", "UNSIGNED48", "UINT48", "UNSIGNED56",
+ "UINT56", "UNSIGNED64", "ULINT"],
+ "int8": ["INTEGER8", "SINT"],
+ "int16": ["INTEGER16", "INT"],
+ "int32": ["INTEGER24", "INT24", "INTEGER32", "DINT"],
+ "int64": ["INTEGER40", "INT40", "INTEGER48", "INT48", "INTEGER56", "INT56",
+ "INTEGER64", "LINT"],
+ "float": ["REAL", "REAL32"],
+ "double": ["LREAL", "REAL64"],
+ "string": ["VISUBLE_STRING", "STRING(n)"],
+ "octet_string": ["OCTET_STRING"],
+ "unicode_string": ["UNICODE_STRING"]
+ }
+
# category of SDO data
DatatypeDescription, CommunicationObject, ManufacturerSpecific, \
ProfileSpecific, Reserved, AllSDOData = range(6)
- # store the execution result of "ethercat sdos" command into SaveSDOData.
- SaveSDOData = []
-
- # Flags for checking "write" permission of OD entries
+ # SDO data informations: index, sub-index, type, bit size, category-name
+ SDOVariables = []
+ SDOSubEntryData = []
+
+ # defalut value of SDO data in XML
+ # Not Used
+ DefaultValueDic = {}
+
+ # Flags for checking "write" permission of OD entries
CheckPREOP = False
CheckSAFEOP = False
CheckOP = False
@@ -241,15 +294,6 @@
# -------------------------------------------------------------------------------
# Used SDO Management
# -------------------------------------------------------------------------------
- def GetSlaveSDOFromSlave(self):
- """
- Get SDO objects information of current slave using "ethercat sdos -p %d" command.
- Command example : "ethercat sdos -p 0"
- @return return_val : execution results of "ethercat sdos" command (need to be parsed later)
- """
- _error, return_val = self.Controler.RemoteExec(SLAVE_SDO % (self.Controler.GetSlavePos()), return_val=None)
- return return_val
-
def SDODownload(self, data_type, idx, sub_idx, value):
"""
Set an SDO object value to user-specified value using "ethercat download" command.
@@ -258,11 +302,14 @@
@param idx : index of the SDO entry
@param sub_idx : subindex of the SDO entry
@param value : value of SDO entry
- """
- _error, _return_val = self.Controler.RemoteExec(
- SDO_DOWNLOAD % (data_type, self.Controler.GetSlavePos(), idx, sub_idx, value),
- return_val=None)
-
+ """
+ valid_type = self.GetValidDataType(data_type)
+ _error, return_val = self.Controler.RemoteExec(
+ SDO_DOWNLOAD%(valid_type, self.Controler.GetSlavePos(),
+ idx, sub_idx, value), return_val = None)
+
+ return return_val
+
def BackupSDODataSet(self):
"""
Back-up current SDO entry information to restore the SDO data
@@ -282,12 +329,316 @@
for dummy in range(6):
self.SaveSDOData.append([])
+ def GetAllSDOValuesFromSlave(self):
+ """
+ Get SDO values of All SDO entries.
+ @return return_val: list of result of "SDO_UPLOAD"
+ """
+ entry_infos = ""
+ alldata_idx = len(self.SDOVariables)
+ counter = 0
+ for category in self.SDOVariables:
+ counter +=1
+ # for avoid redundant repetition
+ if counter == alldata_idx:
+ continue
+
+ for entry in category:
+ valid_type = self.GetValidDataType(entry["type"])
+ for_command_string = "%s %s %s ," % \
+ (valid_type, entry["idx"], entry["subIdx"])
+ entry_infos += for_command_string
+
+ error, return_val = self.Controler.RemoteExec(SDO_UPLOAD%(entry_infos, self.Controler.GetSlavePos()), return_val = None)
+
+ return return_val
+
+ def GetSDOValuesFromSlave(self, entries_info):
+ """
+ Get SDO values of some SDO entries.
+ @param entries_info: dictionary of SDO entries that is wanted to know the value.
+ @return return_val: list of result of "SDO_UPLOAD"
+ """
+ entry_infos = ""
+
+ entries_info_list = entries_info.items()
+ entries_info_list.sort()
+
+ for (idx, subIdx), entry in entries_info_list:
+ valid_type = self.GetValidDataType(entry["type"])
+ for_command_string = "%s %s %s ," % \
+ (valid_type, str(idx), str(subIdx))
+ entry_infos += for_command_string
+
+ error, return_val = self.Controler.RemoteExec(SDO_UPLOAD%(entry_infos, self.Controler.GetSlavePos()), return_val = None)
+
+ return return_val
+
+ def ExtractObjects(self):
+ """
+ Extract object type items from imported ESI xml.
+ And they are stuctured as dictionary.
+ @return objects: dictionary of objects
+ """
+ objects = {}
+
+ slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos())
+ type_infos = slave.getType()
+ device, alignment = self.Controler.CTNParent.GetModuleInfos(type_infos)
+
+ if device is not None :
+ for dictionary in device.GetProfileDictionaries():
+ dictionary.load()
+ for object in dictionary.getObjects().getObject():
+ object_index = ExtractHexDecValue(object.getIndex().getcontent())
+ objects[(object_index)] = object
+
+ return objects
+
+ def ExtractAllDataTypes(self):
+ """
+ Extract all data types from imported ESI xml.
+ @return dataTypes: dictionary of datatypes
+ """
+ dataTypes = {}
+
+ slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos())
+ type_infos = slave.getType()
+ device, alignment = self.Controler.CTNParent.GetModuleInfos(type_infos)
+
+ for dictionary in device.GetProfileDictionaries():
+ dictionary.load()
+
+ datatypes = dictionary.getDataTypes()
+ if datatypes is not None:
+
+ for datatype in datatypes.getDataType():
+ dataTypes[datatype.getName()] = datatype
+ return dataTypes
+
+ def IsBaseDataType(self, datatype):
+ """
+ Check if the datatype is a base data type.
+ @return baseTypeFlag: true if datatype is a base data type, unless false
+ """
+ baseTypeFlag = False
+ for baseDataTypeList in self.BaseDataTypes.values():
+ if datatype in baseDataTypeList:
+ baseTypeFlag = True
+ break
+ return baseTypeFlag
+
+ def GetBaseDataType(self, datatype):
+ """
+ Get a base data type corresponding the datatype.
+ @param datatype: Some data type (string format)
+ @return base data type
+ """
+ if self.IsBaseDataType(datatype):
+ return datatype
+ elif not datatype.find("STRING") == -1:
+ return datatype
+ else:
+ datatypes = self.ExtractAllDataTypes()
+ base_datatype = datatypes[datatype].getBaseType()
+ return self.GetBaseDataType(base_datatype)
+
+ def GetValidDataType(self, datatype):
+ """
+ Convert the datatype into a data type that is possible to download/upload
+ in etherlab master stack.
+ @param datatype: Some data type (string format)
+ @return base_type: vaild data type
+ """
+ base_type = self.GetBaseDataType(datatype)
+
+ if re.match("STRING\([0-9]*\)", datatype) is not None:
+ return "string"
+ else:
+ for key, value in self.BaseDataTypes.items():
+ if base_type in value:
+ return key
+ return base_type
+
+ # Not Used
+ def GetAllEntriesList(self):
+ """
+ Get All entries information that includes index, sub-index, name,
+ type, bit size, PDO mapping, and default value.
+ @return self.entries: dictionary of entry
+ """
+ slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos())
+ type_infos = slave.getType()
+ device, alignment = self.Controler.CTNParent.GetModuleInfos(type_infos)
+ self.entries = device.GetEntriesList()
+ datatypes = self.ExtractAllDataTypes()
+ objects = self.ExtractObjects()
+ entries_list = self.entries.items()
+ entries_list.sort()
+
+ # append sub entries
+ for (index, subidx), entry in entries_list:
+ # entry_* is string type
+ entry_type = entry["Type"]
+ entry_index = entry["Index"]
+
+ try:
+ object_info = objects[index].getInfo()
+ except:
+ continue
+
+ if object_info is not None:
+ obj_content = object_info.getcontent()
+
+ typeinfo = datatypes.get(entry_type, None)
+ bitsize = typeinfo.getBitSize()
+ type_content = typeinfo.getcontent()
+
+ # ArrayInfo type
+ if type_content is not None and type_content["name"] == "ArrayInfo":
+ for arrayinfo in type_content["value"]:
+ element_num = arrayinfo.getElements()
+ first_subidx = arrayinfo.getLBound()
+ for offset in range(element_num):
+ new_subidx = int(first_subidx) + offset
+ entry_subidx = hex(new_subidx)
+ if obj_content["value"][new_subidx]["name"] == "SubItem":
+ subitem = obj_content["value"][new_subidx]["value"]
+ subname = subitem[new_subidx].getName()
+ if subname is not None:
+ entry_name = "%s - %s" % \
+ (ExtractName(objects[index].getName()), subname)
+ else:
+ entry_name = ExtractName(objects[index].getName())
+ self.entries[(index, new_subidx)] = {
+ "Index": entry_index,
+ "SubIndex": entry_subidx,
+ "Name": entry_name,
+ "Type": typeinfo.getBaseType(),
+ "BitSize": str(bitsize/element_num),
+ "Access": entry["Access"],
+ "PDOMapping": entry["PDOMapping"]}
+ try:
+ value_info = subitem[new_subidx].getInfo().getcontent()\
+ ["value"][0]["value"][0]
+ self.AppendDefaultValue(index, new_subidx, value_info)
+ except:
+ pass
+
+ try:
+ value_info = subitem[subidx].getInfo().getcontent()\
+ ["value"][0]["value"][0]
+ self.AppendDefaultValue(index, subidx, value_info)
+ except:
+ pass
+
+ # EnumInfo type
+ elif type_content is not None and type_content["name"] == "EnumInfo":
+ self.entries[(index, subidx)]["EnumInfo"] = {}
+
+ for enuminfo in type_content["value"]:
+ text = enuminfo.getText()
+ enum = enuminfo.getEnum()
+ self.entries[(index, subidx)]["EnumInfo"][str(enum)] = text
+
+ self.entries[(index, subidx)]["DefaultValue"] = "0x00"
+
+ # another types
+ else:
+ if subidx == 0x00:
+ tmp_subidx = 0x00
+
+ try:
+ if obj_content["value"][tmp_subidx]["name"] == "SubItem":
+ sub_name = entry["Name"].split(" - ")[1]
+ for num in range(len(obj_content["value"])):
+ if sub_name == \
+ obj_content["value"][num]["value"][num].getName():
+ subitem_content = obj_content["value"][tmp_subidx]\
+ ["value"][tmp_subidx]
+ value_info = subitem_content.getInfo().getcontent()\
+ ["value"][0]["value"][0]
+ tmp_subidx += 1
+ break
+ else:
+ value_info = None
+
+ else:
+ value_info = \
+ obj_content["value"][tmp_subidx]["value"][tmp_subidx]
+
+ self.AppendDefaultValue(index, subidx, value_info)
+
+ except:
+ pass
+
+ return self.entries
+
+ # Not Used
+ def AppendDefaultValue(self, index, subidx, value_info=None):
+ """
+ Get the default value from the ESI xml
+ @param index: entry index
+ @param subidx: entry sub index
+ @param value_info: dictionary of infomation about default value
+
+ """
+ # there is not default value.
+ if value_info == None:
+ return
+
+ raw_value = value_info["value"]
+
+ # default value is hex binary type.
+ if value_info["name"] == "DefaultData":
+ raw_value_bit = list(hex(raw_value).split("0x")[1])
+
+ datatype = self.GetValidDataType(self.entries[(index, subidx)]["Type"])
+ if datatype is "string" or datatype is "octet_string":
+
+ if "L" in raw_value_bit:
+ raw_value_bit.remove("L")
+
+ default_value = "".join(raw_value_bit).decode("hex")
+
+ elif datatype is "unicode_string":
+ default_value = "".join(raw_value_bit).decode("hex").\
+ decode("utf-8")
+
+ else:
+ bit_num = len(raw_value_bit)
+ # padding
+ if not bit_num%2 == 0:
+ raw_value_bit.insert(0, "0")
+
+ default_value_bit = []
+
+ # little endian -> big endian
+ for num in range(bit_num):
+ if num%2 == 0:
+ default_value_bit.insert(0, raw_value_bit[num])
+ default_value_bit.insert(1, raw_value_bit[num+1])
+
+ default_value = "0x%s" % "".join(default_value_bit)
+
+ # default value is string type.
+ # this case is not tested yet.
+ elif value_info["name"] == "DefaultString":
+ default_value = raw_value
+
+ # default value is Hex or Dec type.
+ elif value_info["name"] == "DefaultValue":
+ default_value = "0x" + hex(ExtractHexDecValue(raw_value))
+
+ self.entries[(index, subidx)]["DefaultValue"] = default_value
+
# -------------------------------------------------------------------------------
# Used PDO Monitoring
# -------------------------------------------------------------------------------
def RequestPDOInfo(self):
"""
- Load slave information from RootClass (XML data) and parse the information (calling SlavePDOData() method).
+ Load slave information from RootClass (XML data) and parse the information
+ (calling SlavePDOData() method).
"""
# Load slave information from ESI XML file (def EthercatMaster.py)
slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos())
@@ -314,6 +665,13 @@
pdo_index = ExtractHexDecValue(pdo.getIndex().getcontent())
entries = pdo.getEntry()
pdo_name = ExtractName(pdo.getName())
+ excludes = pdo.getExclude()
+ exclude_list = []
+ Sm = pdo.getSm()
+
+ if excludes :
+ for exclude in excludes:
+ exclude_list.append(ExtractHexDecValue(exclude.getcontent()))
# Initialize entry number count
count = 0
@@ -329,13 +687,15 @@
"entry_index": index,
"subindex": subindex,
"name": ExtractName(entry.getName()),
- "bitlen": entry.getBitLen(),
- "type": entry.getDataType().getcontent()
+ "bitlen": entry.getBitLen()
}
+ if entry.getDataType() is not None:
+ entry_infos["type"] = entry.getDataType().getcontent()
self.TxPDOInfo.append(entry_infos)
count += 1
- categorys = {"pdo_index": pdo_index, "name": pdo_name, "number_of_entry": count}
+ categorys = {"pdo_index" : pdo_index, "name" : pdo_name, "sm" : Sm,
+ "number_of_entry" : count, "exclude_list" : exclude_list}
self.TxPDOCategory.append(categorys)
# Parsing RxPDO entries
@@ -344,6 +704,13 @@
pdo_index = ExtractHexDecValue(pdo.getIndex().getcontent())
entries = pdo.getEntry()
pdo_name = ExtractName(pdo.getName())
+ excludes = pdo.getExclude()
+ exclude_list = []
+ Sm = pdo.getSm()
+
+ if excludes :
+ for exclude in excludes:
+ exclude_list.append(ExtractHexDecValue(exclude.getcontent()))
# Initialize entry number count
count = 0
@@ -359,14 +726,16 @@
"entry_index": index,
"subindex": subindex,
"name": ExtractName(entry.getName()),
- "bitlen": str(entry.getBitLen()),
- "type": entry.getDataType().getcontent()
+ "bitlen": str(entry.getBitLen())
}
+ if entry.getDataType() is not None:
+ entry_infos["type"] = entry.getDataType().getcontent()
self.RxPDOInfo.append(entry_infos)
count += 1
- categorys = {"pdo_index": pdo_index, "name": pdo_name, "number_of_entry": count}
- self.RxPDOCategory.append(categorys)
+ categorys = {"pdo_index" : pdo_index, "name" : pdo_name, "sm" : Sm,
+ "number_of_entry" : count, "exclude_list" : exclude_list}
+ self.RxPDOCategory.append(categorys)
def GetTxPDOCategory(self):
"""
@@ -404,10 +773,10 @@
"""
Initialize PDO management data structure.
"""
- self.TxPDOInfos = []
- self.TxPDOCategorys = []
- self.RxPDOInfos = []
- self.RxPDOCategorys = []
+ self.TxPDOInfo = []
+ self.TxPDOCategory = []
+ self.RxPDOInfo = []
+ self.RxPDOCategory = []
# -------------------------------------------------------------------------------
# Used EEPROM Management
@@ -496,11 +865,11 @@
smartview_infos[cfg] = str(int(bootstrap_data[4*iter+2:4*(iter+1)]+bootstrap_data[4*iter:4*iter+2], 16))
# get protocol (profile) types supported by mailbox; <Device>-<Mailbox>
- mb = device.getMailbox()
- if mb is not None:
- for mailbox_protocol in mailbox_protocols:
- if getattr(mb, "get%s" % mailbox_protocol)() is not None:
- smartview_infos["supported_mailbox"] += "%s, " % mailbox_protocol
+ with device.getMailbox() as mb:
+ if mb is not None:
+ for mailbox_protocol in mailbox_protocols:
+ if getattr(mb, "get%s" % mailbox_protocol)() is not None:
+ smartview_infos["supported_mailbox"] += "%s, " % mailbox_protocol
smartview_infos["supported_mailbox"] = smartview_infos["supported_mailbox"].strip(", ")
# get standard configuration of mailbox; <Device>-<Sm>
@@ -515,24 +884,24 @@
pass
# get device identity from <Device>-<Type>
- # vendor ID; by default, pre-defined value in self.ModulesLibrary
- # if device type in 'vendor' item equals to actual slave device type, set 'vendor_id' to vendor ID.
+ # vendor ID; by default, pre-defined value in self.ModulesLibrary
+ # if device type in 'vendor' item equals to actual slave device type, set 'vendor_id' to vendor ID.
for vendor_id, vendor in self.Controler.CTNParent.CTNParent.ModulesLibrary.Library.iteritems():
for available_device in vendor["groups"][vendor["groups"].keys()[0]]["devices"]:
if available_device[0] == type_infos["device_type"]:
smartview_infos["vendor_id"] = "0x" + "{:0>8x}".format(vendor_id)
- # product code;
+ # product code;
if device.getType().getProductCode() is not None:
product_code = device.getType().getProductCode()
smartview_infos["product_code"] = "0x"+"{:0>8x}".format(ExtractHexDecValue(product_code))
- # revision number;
+ # revision number;
if device.getType().getRevisionNo() is not None:
revision_no = device.getType().getRevisionNo()
smartview_infos["revision_no"] = "0x"+"{:0>8x}".format(ExtractHexDecValue(revision_no))
- # serial number;
+ # serial number;
if device.getType().getSerialNo() is not None:
serial_no = device.getType().getSerialNo()
smartview_infos["serial_no"] = "0x"+"{:0>8x}".format(ExtractHexDecValue(serial_no))
@@ -548,14 +917,14 @@
@param decnum : decimal value
@return hex_data : hexadecimal representation of input value in decimal
"""
- value = "%x" % decnum
+ value = "%x" % int(decnum, 16)
value_len = len(value)
if (value_len % 2) == 0:
hex_len = value_len
else:
hex_len = (value_len // 2) * 2 + 2
- hex_data = ("{:0>"+str(hex_len)+"x}").format(decnum)
+ hex_data = ("{:0>"+str(hex_len)+"x}").format(int(decnum, 16))
return hex_data
@@ -750,7 +1119,7 @@
data = ""
for eeprom_element in device.getEeprom().getcontent():
if eeprom_element["name"] == "BootStrap":
- data = "{:0>16x}".format(eeprom_element)
+ data = "{:0>16x}".format(int(eeprom_element,16))
eeprom += self.GenerateEEPROMList(data, 0, 16)
# get Standard Mailbox for EEPROM offset 0x0030-0x0037; <Device>-<sm>
@@ -794,11 +1163,11 @@
# get supported mailbox protocols for EEPROM offset 0x0038-0x0039;
data = 0
- mb = device.getMailbox()
- if mb is not None:
- for bit, mbprot in enumerate(mailbox_protocols):
- if getattr(mb, "get%s" % mbprot)() is not None:
- data += 1 << bit
+ with device.getMailbox() as mb:
+ if mb is not None:
+ for bit, mbprot in enumerate(mailbox_protocols):
+ if getattr(mb, "get%s" % mbprot)() is not None:
+ data += 1 << bit
data = "{:0>4x}".format(data)
eeprom.append(data[2:4])
eeprom.append(data[0:2])
@@ -808,11 +1177,12 @@
eeprom.append("00")
# get EEPROM size for EEPROM offset 0x007c-0x007d;
+ # Modify by jblee because of update IDE module (minidom -> lxml)
data = ""
- for eeprom_element in device.getEeprom().getcontent():
- if eeprom_element["name"] == "ByteSize":
- eeprom_size = int(str(eeprom_element))
- data = "{:0>4x}".format(int(eeprom_element)//1024*8-1)
+ for eeprom_element in device.getEeprom().getchildren():
+ if eeprom_element.tag == "ByteSize":
+ eeprom_size = int(objectify.fromstring(eeprom_element.tostring()).text)
+ data = "{:0>4x}".format(eeprom_size/1024*8-1)
if data == "":
eeprom.append("00")
@@ -822,7 +1192,7 @@
eeprom.append(data[0:2])
# Version for EEPROM 0x007e-0x007f;
- # According to "EtherCAT Slave Device Description(V0.3.0)"
+ # According to "EtherCAT Slave Device Description(V0.3.0)"
eeprom.append("01")
eeprom.append("00")
@@ -915,7 +1285,7 @@
vendor_specific_data += "{:0>2x}".format(ord(data[character]))
data = ""
- # element2-1; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<GroupType>
+ # element2-1; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<GroupType>
data = device.getGroupType()
if data is not None and isinstance(data, text):
for vendor_spec_string in vendor_spec_strings:
@@ -978,6 +1348,7 @@
vendor_specific_data += "{:0>2x}".format(len(data))
for character in range(len(data)):
vendor_specific_data += "{:0>2x}".format(ord(data[character]))
+
data = ""
# element4; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Name(LcId is "1033" or "1"?)>
@@ -1183,42 +1554,41 @@
# word 3 : Physical Layer Port info. and CoE Details
eeprom.append("01") # Physical Layer Port info - assume 01
# CoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<CoE>
- coe_details = 0
- mb = device.getMailbox()
coe_details = 1 # sdo enabled
- if mb is not None:
- coe = mb.getCoE()
- if coe is not None:
- for bit, flag in enumerate(["SdoInfo", "PdoAssign", "PdoConfig",
- "PdoUpload", "CompleteAccess"]):
- if getattr(coe, "get%s" % flag)() is not None:
- coe_details += 1 << bit
- eeprom.append("{:0>2x}".format(coe_details))
-
- # word 4 : FoE Details and EoE Details
- # FoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<FoE>
- if mb is not None and mb.getFoE() is not None:
- eeprom.append("01")
- else:
- eeprom.append("00")
- # EoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<EoE>
- if mb is not None and mb.getEoE() is not None:
- eeprom.append("01")
- else:
- eeprom.append("00")
-
- # word 5 : SoE Channels(reserved) and DS402 Channels
- # SoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<SoE>
- if mb is not None and mb.getSoE() is not None:
- eeprom.append("01")
- else:
- eeprom.append("00")
- # DS402Channels; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<CoE>: DS402Channels
- ds402ch = False
- if mb is not None:
- coe = mb.getCoE()
- if coe is not None:
- ds402ch = coe.getDS402Channels()
+ with device.getMailbox() as mb
+ if mb is not None:
+ coe = mb.getCoE()
+ if coe is not None:
+ for bit, flag in enumerate(["SdoInfo", "PdoAssign", "PdoConfig",
+ "PdoUpload", "CompleteAccess"]):
+ if getattr(coe, "get%s" % flag)() is not None:
+ coe_details += 1 << bit
+ eeprom.append("{:0>2x}".format(coe_details))
+
+ # word 4 : FoE Details and EoE Details
+ # FoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<FoE>
+ if mb is not None and mb.getFoE() is not None:
+ eeprom.append("01")
+ else:
+ eeprom.append("00")
+ # EoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<EoE>
+ if mb is not None and mb.getEoE() is not None:
+ eeprom.append("01")
+ else:
+ eeprom.append("00")
+
+ # word 5 : SoE Channels(reserved) and DS402 Channels
+ # SoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<SoE>
+ if mb is not None and mb.getSoE() is not None:
+ eeprom.append("01")
+ else:
+ eeprom.append("00")
+ # DS402Channels; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<CoE>: DS402Channels
+ ds402ch = False
+ if mb is not None:
+ coe = mb.getCoE()
+ if coe is not None:
+ ds402ch = coe.getDS402Channels()
eeprom.append("01" if ds402ch in [True, 1] else "00")
# word 6 : SysmanClass(reserved) and Flags
@@ -1546,6 +1916,24 @@
return_val=None)
return return_val
+ def MultiRegRead(self, slave_num, reg_infos):
+ """
+
+ @slave_num:
+ @param addr_info:
+ @return return_val:
+ """
+ reg_info_str = ""
+ for reg_info in reg_infos:
+ reg_info_str = reg_info_str + "%s|" % reg_info
+ reg_info_str = reg_info_str.strip("|")
+
+ _error, return_val = self.Controler.RemoteExec(\
+ MULTI_REG_READ%(slave_num, reg_info_str),
+ return_val = None)
+
+ return return_val
+
def RegWrite(self, address, data):
"""
Write data to slave ESC register using "ethercat reg_write -p %d %s %s" command.
@@ -1567,6 +1955,40 @@
_error, _return_val = self.Controler.RemoteExec(RESCAN % (self.Controler.GetSlavePos()), return_val=None)
# -------------------------------------------------------------------------------
+ # Used DC Configuration
+ #-------------------------------------------------------------------------------
+ def LoadESIData(self):
+ return_data = []
+ slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos())
+ type_infos = slave.getType()
+ device, alignment = self.Controler.CTNParent.GetModuleInfos(type_infos)
+ if device.getDc() is not None:
+ for OpMode in device.getDc().getOpMode():
+ temp_data = {
+ "desc" : OpMode.getDesc() if OpMode.getDesc() is not None else "Unused",
+ "assign_activate" : OpMode.getAssignActivate() \
+ if OpMode.getAssignActivate() is not None else "#x0000",
+ "cycletime_sync0" : OpMode.getCycleTimeSync0().getcontent() \
+ if OpMode.getCycleTimeSync0() is not None else None,
+ "shifttime_sync0" : OpMode.getShiftTimeSync0().getcontent() \
+ if OpMode.getShiftTimeSync0() is not None else None,
+ "cycletime_sync1" : OpMode.getShiftTimeSync1().getcontent() \
+ if OpMode.getShiftTimeSync1() is not None else None,
+ "shifttime_sync1" : OpMode.getShiftTimeSync1().getcontent() \
+ if OpMode.getShiftTimeSync1() is not None else None
+ }
+
+ if OpMode.getCycleTimeSync0() is not None:
+ temp_data["cycletime_sync0_factor"] = OpMode.getCycleTimeSync0().getFactor()
+
+ if OpMode.getCycleTimeSync1() is not None:
+ temp_data["cycletime_sync1_factor"] = OpMode.getCycleTimeSync1().getFactor()
+
+ return_data.append(temp_data)
+
+ return return_data
+
+ #-------------------------------------------------------------------------------
# Common Use Methods
# -------------------------------------------------------------------------------
def CheckConnect(self, cyclic_flag):