andrej@2354: #!/usr/bin/env python
andrej@2354: # -*- coding: utf-8 -*-
andrej@2354: 
andrej@2354: 
andrej@2354: # This file is part of Beremiz
andrej@2354: #
andrej@2354: # Copyright (C) 2013: Real-Time & Embedded Systems (RTES) Lab. University of Seoul, Korea
andrej@2354: #
andrej@2354: # See COPYING file for copyrights details.
andrej@2354: 
andrej@2405: from __future__ import absolute_import
andrej@2437: from __future__ import division
andrej@2434: from builtins import str as text
andrej@2446: import codecs
andrej@2354: import wx
andrej@2354: 
andrej@2434: 
andrej@2373: mailbox_protocols = ["AoE", "EoE", "CoE", "FoE", "SoE", "VoE"]
andrej@2354: 
andrej@2360: 
andrej@2354: def ExtractHexDecValue(value):
andrej@2354:     """
andrej@2354:      convert numerical value in string format into decimal or hex format.
andrej@2354:      @param value : hex or decimal data
andrej@2354:      @return integer data
andrej@2354:     """
andrej@2354:     try:
andrej@2354:         return int(value)
andrej@2354:     except Exception:
andrej@2354:         pass
andrej@2354:     try:
andrej@2354:         return int(value.replace("#", "0"), 16)
andrej@2355: 
andrej@2354:     except Exception:
andrej@2423:         raise ValueError(_("Invalid value for HexDecValue \"%s\"") % value)
andrej@2354: 
andrej@2360: 
andrej@2354: def ExtractName(names, default=None):
andrej@2354:     """
andrej@2354:      Extract "name" field from XML entries.
andrej@2354:      @param names : XML entry
andrej@2354:      @default : if it fails to extract from the designated XML entry, return the default value ("None").
andrej@2354:      @return default or the name extracted
andrej@2354:     """
andrej@2354:     if len(names) == 1:
andrej@2354:         return names[0].getcontent()
andrej@2354:     else:
andrej@2354:         for name in names:
andrej@2354:             if name.getLcId() == 1033:
andrej@2354:                 return name.getcontent()
andrej@2354:     return default
andrej@2354: 
edouard@2643: #--------------------------------------------------
andrej@2354: #         Remote Exec Etherlab Commands
edouard@2643: #--------------------------------------------------
andrej@2370: 
andrej@2354: # --------------------- for master ---------------------------
andrej@2354: MASTER_STATE = """
andrej@2354: import commands
andrej@2354: result = commands.getoutput("ethercat master")
andrej@2355: returnVal =result
andrej@2354: """
andrej@2354: 
andrej@2354: # --------------------- for slave ----------------------------
andrej@2354: # ethercat state -p (slave position) (state (INIT, PREOP, SAFEOP, OP))
andrej@2354: SLAVE_STATE = """
andrej@2354: import commands
andrej@2354: result = commands.getoutput("ethercat state -p %d %s")
andrej@2355: returnVal = result
andrej@2354: """
andrej@2354: 
andrej@2354: # ethercat slave
andrej@2354: GET_SLAVE = """
andrej@2354: import commands
andrej@2354: result = commands.getoutput("ethercat slaves")
andrej@2355: returnVal =result
andrej@2354: """
andrej@2354: 
andrej@2354: # ethercat xml -p (slave position)
andrej@2354: SLAVE_XML = """
andrej@2354: import commands
andrej@2354: result = commands.getoutput("ethercat xml -p %d")
andrej@2355: returnVal = result
andrej@2354: """
andrej@2354: 
edouard@2643: # ethercat upload -p (slave position) -t (type) (index) (sub index)
edouard@2643: SDO_UPLOAD = """
andrej@2354: import commands
edouard@2643: sdo_data = []
edouard@2643: input_data = "%s"
edouard@2643: slave_pos = %d
edouard@2643: command_string = ""
edouard@2643: for sdo_token in input_data.split(","):  
edouard@2643:     if len(sdo_token) > 1:
edouard@2643:         sdo_token = sdo_token.strip()
edouard@2643:         type, idx, subidx = sdo_token.split(" ")
edouard@2643:         command_string = "ethercat upload -p " + str(slave_pos) + " -t " + type + " " + idx + " " + subidx
edouard@2643:         result = commands.getoutput(command_string)
edouard@2643:         sdo_data.append(result)
edouard@2643: returnVal =sdo_data
andrej@2354: """
andrej@2354: 
andrej@2354: # ethercat download -p (slave position) (main index) (sub index) (value)
andrej@2354: SDO_DOWNLOAD = """
andrej@2354: import commands
andrej@2354: result = commands.getoutput("ethercat download --type %s -p %d %s %s %s")
andrej@2355: returnVal =result
andrej@2354: """
andrej@2354: 
andrej@2354: # ethercat sii_read -p (slave position)
andrej@2354: SII_READ = """
andrej@2354: import commands
andrej@2354: result = commands.getoutput("ethercat sii_read -p %d")
andrej@2355: returnVal =result
andrej@2354: """
andrej@2354: 
andrej@2354: # ethercat reg_read -p (slave position) (address) (size)
andrej@2354: REG_READ = """
andrej@2354: import commands
andrej@2354: result = commands.getoutput("ethercat reg_read -p %d %s %s")
andrej@2355: returnVal =result
andrej@2354: """
andrej@2354: 
edouard@2643: # ethercat reg_read -p (slave position) (address) (size)
edouard@2643: MULTI_REG_READ = """ 
edouard@2643: import commands
edouard@2643: output = []
edouard@2643: addr, size = range(2)
edouard@2643: slave_num = %d 
edouard@2643: reg_info_str = "%s"
edouard@2643: reg_info_list = reg_info_str.split("|")
edouard@2643: for slave_idx in range(slave_num):
edouard@2643:     for reg_info in reg_info_list:
edouard@2643:         param = reg_info.split(",")
edouard@2643:         result = commands.getoutput("ethercat reg_read -p "
edouard@2643:                                     + str(slave_idx) + " "
edouard@2643:                                     + param[addr] + " "
edouard@2643:                                     + param[size])
edouard@2643:         output.append(str(slave_idx) + "," + param[addr] + "," + result)
edouard@2643: returnVal = output
edouard@2643: """
edouard@2643: 
andrej@2354: # ethercat sii_write -p (slave position) - (contents)
andrej@2355: SII_WRITE = """
andrej@2355: import subprocess
andrej@2354: process = subprocess.Popen(
andrej@2354:     ["ethercat", "-f", "sii_write", "-p", "%d", "-"],
andrej@2354:     stdin=subprocess.PIPE)
andrej@2354: process.communicate(sii_data)
andrej@2355: returnVal = process.returncode
andrej@2354: """
andrej@2354: 
andrej@2354: # ethercat reg_write -p (slave position) -t (uinit16) (address) (data)
andrej@2355: REG_WRITE = """
andrej@2354: import commands
andrej@2354: result = commands.getoutput("ethercat reg_write -p %d -t uint16 %s %s")
andrej@2355: returnVal =result
andrej@2355: """
andrej@2354: 
andrej@2354: # ethercat rescan -p (slave position)
andrej@2355: RESCAN = """
andrej@2354: import commands
andrej@2354: result = commands.getoutput("ethercat rescan -p %d")
andrej@2355: returnVal =result
andrej@2354: """
andrej@2354: 
edouard@2643: # ethercat pdos
edouard@2643: PDOS = """
edouard@2643: import commands
edouard@2643: result = commands.getoutput("ethercat pdos -p 0")
edouard@2643: returnVal =result  
edouard@2643: """
andrej@2360: 
andrej@2356: # --------------------------------------------------
andrej@2355: #    Common Method For EtherCAT Management
andrej@2356: # --------------------------------------------------
andrej@2397: class _CommonSlave(object):
andrej@2354: 
andrej@2354:     # ----- Data Structure for ethercat management ----
andrej@2354:     SlaveState = ""
andrej@2354: 
edouard@2643:     # SDO base data type for Ethercatmaster
edouard@2643:     BaseDataTypes = {
edouard@2643:             "bool": ["BOOLEAN", "BOOL", "BIT"],
edouard@2643:             "uint8": ["BYTE", "USINT", "BIT1", "BIT2", "BIT3", "BIT4", "BIT5", "BIT6",
edouard@2643:                       "BIT7", "BIT8", "BITARR8", "UNSIGNED8"],
edouard@2643:             "uint16": ["BITARR16", "UNSIGNED16", "UINT"],
edouard@2643:             "uint32": ["BITARR32", "UNSIGNED24", "UINT24", "UNSIGNED32", "UDINT"],
edouard@2643:             "uint64": ["UNSINED40", "UINT40", "UNSIGNED48", "UINT48", "UNSIGNED56", 
edouard@2643:                        "UINT56", "UNSIGNED64", "ULINT"],
edouard@2643:             "int8": ["INTEGER8", "SINT"],
edouard@2643:             "int16": ["INTEGER16", "INT"],
edouard@2643:             "int32": ["INTEGER24", "INT24", "INTEGER32", "DINT"],
edouard@2643:             "int64": ["INTEGER40", "INT40", "INTEGER48", "INT48", "INTEGER56", "INT56",
edouard@2643:                       "INTEGER64", "LINT"],
edouard@2643:             "float": ["REAL", "REAL32"],
edouard@2643:             "double": ["LREAL", "REAL64"],
edouard@2643:             "string": ["VISUBLE_STRING", "STRING(n)"],
edouard@2643:             "octet_string": ["OCTET_STRING"],
edouard@2643:             "unicode_string": ["UNICODE_STRING"]
edouard@2643:             }
edouard@2643:     
andrej@2354:     # category of SDO data
andrej@2354:     DatatypeDescription, CommunicationObject, ManufacturerSpecific, \
andrej@2384:         ProfileSpecific, Reserved, AllSDOData = range(6)
andrej@2355: 
edouard@2643:     # SDO data informations: index, sub-index, type, bit size, category-name 
edouard@2643:     SDOVariables = []
edouard@2643:     SDOSubEntryData = []
edouard@2643:     
edouard@2643:     # defalut value of SDO data in XML
edouard@2643:     # Not Used
edouard@2643:     DefaultValueDic = {}
edouard@2643:     
edouard@2643:     # Flags for checking "write" permission of OD entries 
andrej@2354:     CheckPREOP = False
andrej@2354:     CheckSAFEOP = False
andrej@2354:     CheckOP = False
andrej@2354: 
andrej@2354:     # Save PDO Data
andrej@2354:     TxPDOInfo = []
andrej@2354:     TxPDOCategory = []
andrej@2354:     RxPDOInfo = []
andrej@2354:     RxPDOCategory = []
andrej@2355: 
andrej@2354:     # Save EEPROM Data
andrej@2354:     SiiData = ""
andrej@2354: 
andrej@2354:     # Save Register Data
andrej@2354:     RegData = ""
andrej@2354:     CrtRegSpec = {"ESCType": "",
andrej@2354:                   "FMMUNumber": "",
andrej@2354:                   "SMNumber": "",
andrej@2354:                   "PDIType": ""}
andrej@2355: 
andrej@2354:     def __init__(self, controler):
andrej@2354:         """
andrej@2354:         Constructor
andrej@2354:         @param controler: _EthercatSlaveCTN class in EthercatSlave.py
andrej@2354:         """
andrej@2354:         self.Controler = controler
andrej@2446:         self.HexDecode = codecs.getdecoder("hex_codec")
andrej@2354:         self.ClearSDODataSet()
andrej@2355: 
andrej@2356:     # -------------------------------------------------------------------------------
andrej@2354:     #                        Used Master State
andrej@2356:     # -------------------------------------------------------------------------------
andrej@2354:     def GetMasterState(self):
andrej@2354:         """
andrej@2354:         Execute "ethercat master" command and parse the execution result
andrej@2355:         @return MasterState
andrej@2355:         """
andrej@2355: 
andrej@2355:         # exectute "ethercat master" command
andrej@2406:         _error, return_val = self.Controler.RemoteExec(MASTER_STATE, return_val=None)
andrej@2354:         master_state = {}
andrej@2354:         # parse the reslut
andrej@2354:         for each_line in return_val.splitlines():
andrej@2375:             if len(each_line) > 0:
andrej@2354:                 chunks = each_line.strip().split(':', 1)
andrej@2354:                 key = chunks[0]
andrej@2354:                 value = []
andrej@2375:                 if len(chunks) > 1:
andrej@2354:                     value = chunks[1].split()
andrej@2354:                 if '(attached)' in value:
andrej@2354:                     value.remove('(attached)')
andrej@2354:                 master_state[key] = value
andrej@2355: 
andrej@2355:         return master_state
andrej@2355: 
andrej@2356:     # -------------------------------------------------------------------------------
andrej@2354:     #                        Used Slave State
andrej@2356:     # -------------------------------------------------------------------------------
andrej@2354:     def RequestSlaveState(self, command):
andrej@2354:         """
andrej@2354:         Set slave state to the specified one using "ethercat states -p %d %s" command.
andrej@2354:         Command example : "ethercat states -p 0 PREOP" (target slave position and target state are given.)
andrej@2355:         @param command : target slave state
andrej@2354:         """
andrej@2406:         _error, _return_val = self.Controler.RemoteExec(
andrej@2406:             SLAVE_STATE % (self.Controler.GetSlavePos(), command),
andrej@2406:             return_val=None)
andrej@2355: 
andrej@2355:     def GetSlaveStateFromSlave(self):
andrej@2355:         """
andrej@2355:         Get slave information using "ethercat slaves" command and store the information into internal data structure
andrej@2355:         (self.SlaveState) for "Slave State"
andrej@2354:         return_val example : 0  0:0  PREOP  +  EL9800 (V4.30) (PIC24, SPI, ET1100)
andrej@2355:         """
andrej@2406:         _error, return_val = self.Controler.RemoteExec(GET_SLAVE, return_val=None)
andrej@2354:         self.SlaveState = return_val
andrej@2355:         return return_val
andrej@2354: 
andrej@2356:     # -------------------------------------------------------------------------------
andrej@2354:     #                        Used SDO Management
andrej@2356:     # -------------------------------------------------------------------------------
andrej@2354:     def SDODownload(self, data_type, idx, sub_idx, value):
andrej@2354:         """
andrej@2354:         Set an SDO object value to user-specified value using "ethercat download" command.
andrej@2354:         Command example : "ethercat download --type int32 -p 0 0x8020 0x12 0x00000000"
andrej@2354:         @param data_type : data type of SDO entry
andrej@2354:         @param idx : index of the SDO entry
andrej@2354:         @param sub_idx : subindex of the SDO entry
andrej@2354:         @param value : value of SDO entry
edouard@2643:         """ 
edouard@2643:         valid_type = self.GetValidDataType(data_type)
edouard@2643:         _error, return_val = self.Controler.RemoteExec(
edouard@2643:             SDO_DOWNLOAD%(valid_type, self.Controler.GetSlavePos(),
edouard@2643:                 idx, sub_idx, value), return_val = None)
edouard@2643:         
edouard@2643:         return return_val
edouard@2643:     
andrej@2354:     def BackupSDODataSet(self):
andrej@2354:         """
andrej@2355:         Back-up current SDO entry information to restore the SDO data
andrej@2383:         in case that the user cancels SDO update operation.
andrej@2383:         """
andrej@2354:         self.BackupDatatypeDescription = self.SaveDatatypeDescription
andrej@2354:         self.BackupCommunicationObject = self.SaveCommunicationObject
andrej@2354:         self.BackupManufacturerSpecific = self.SaveManufacturerSpecific
andrej@2354:         self.BackupProfileSpecific = self.SaveProfileSpecific
andrej@2354:         self.BackupReserved = self.SaveReserved
andrej@2354:         self.BackupAllSDOData = self.SaveAllSDOData
andrej@2355: 
andrej@2354:     def ClearSDODataSet(self):
andrej@2354:         """
andrej@2354:         Clear the specified SDO entry information.
andrej@2355:         """
andrej@2406:         for dummy in range(6):
andrej@2354:             self.SaveSDOData.append([])
andrej@2355: 
edouard@2643:     def GetAllSDOValuesFromSlave(self):
edouard@2643:         """
edouard@2643:         Get SDO values of All SDO entries.
edouard@2643:         @return return_val: list of result of "SDO_UPLOAD"
edouard@2643:         """
edouard@2643:         entry_infos = ""
edouard@2643:         alldata_idx = len(self.SDOVariables)
edouard@2643:         counter = 0
edouard@2643:         for category in self.SDOVariables:
edouard@2643:             counter +=1
edouard@2643:             # for avoid redundant repetition 
edouard@2643:             if counter == alldata_idx:
edouard@2643:                 continue
edouard@2643:             
edouard@2643:             for entry in category:
edouard@2643:                 valid_type = self.GetValidDataType(entry["type"])
edouard@2643:                 for_command_string = "%s %s %s ," % \
edouard@2643:                         (valid_type, entry["idx"], entry["subIdx"])
edouard@2643:                 entry_infos += for_command_string
edouard@2643:              
edouard@2643:         error, return_val = self.Controler.RemoteExec(SDO_UPLOAD%(entry_infos, self.Controler.GetSlavePos()), return_val = None)
edouard@2643:         
edouard@2643:         return return_val
edouard@2643: 
edouard@2643:     def GetSDOValuesFromSlave(self, entries_info):
edouard@2643:         """
edouard@2643:         Get SDO values of some SDO entries.
edouard@2643:         @param entries_info: dictionary of SDO entries that is wanted to know the value. 
edouard@2643:         @return return_val: list of result of "SDO_UPLOAD"
edouard@2643:         """
edouard@2643:         entry_infos = ""
edouard@2643: 
edouard@2643:         entries_info_list = entries_info.items()
edouard@2643:         entries_info_list.sort()
edouard@2643:         
edouard@2643:         for (idx, subIdx), entry in entries_info_list:
edouard@2643:             valid_type = self.GetValidDataType(entry["type"])
edouard@2643:             for_command_string = "%s %s %s ," % \
edouard@2643:                         (valid_type, str(idx), str(subIdx))
edouard@2643:             entry_infos += for_command_string
edouard@2643: 
edouard@2643:         error, return_val = self.Controler.RemoteExec(SDO_UPLOAD%(entry_infos, self.Controler.GetSlavePos()), return_val = None)
edouard@2643:         
edouard@2643:         return return_val
edouard@2643: 
edouard@2643:     def ExtractObjects(self):
edouard@2643:         """
edouard@2643:         Extract object type items from imported ESI xml.
edouard@2643:         And they are stuctured as dictionary.
edouard@2643:         @return objects: dictionary of objects
edouard@2643:         """
edouard@2643:         objects = {}
edouard@2643: 
edouard@2643:         slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos())
edouard@2643:         type_infos = slave.getType()
edouard@2643:         device, alignment = self.Controler.CTNParent.GetModuleInfos(type_infos)
edouard@2643:          
edouard@2643:         if device is not None :
edouard@2643:             for dictionary in device.GetProfileDictionaries():
edouard@2643:                 dictionary.load()
edouard@2643:                 for object in dictionary.getObjects().getObject():
edouard@2643:                     object_index = ExtractHexDecValue(object.getIndex().getcontent())
edouard@2643:                     objects[(object_index)] = object
edouard@2643:         
edouard@2643:         return objects
edouard@2643: 
edouard@2643:     def ExtractAllDataTypes(self):
edouard@2643:         """
edouard@2643:         Extract all data types from imported ESI xml.
edouard@2643:         @return dataTypes: dictionary of datatypes 
edouard@2643:         """
edouard@2643:         dataTypes = {}
edouard@2643:         
edouard@2643:         slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos())
edouard@2643:         type_infos = slave.getType()
edouard@2643:         device, alignment = self.Controler.CTNParent.GetModuleInfos(type_infos)
edouard@2643: 
edouard@2643:         for dictionary in device.GetProfileDictionaries():
edouard@2643:             dictionary.load()
edouard@2643:         
edouard@2643:             datatypes = dictionary.getDataTypes()
edouard@2643:             if datatypes is not None:
edouard@2643: 
edouard@2643:                 for datatype in datatypes.getDataType():
edouard@2643:                     dataTypes[datatype.getName()] = datatype
edouard@2643:         return dataTypes
edouard@2643:     
edouard@2643:     def IsBaseDataType(self, datatype):
edouard@2643:         """
edouard@2643:         Check if the datatype is a base data type.
edouard@2643:         @return baseTypeFlag: true if datatype is a base data type, unless false
edouard@2643:         """
edouard@2643:         baseTypeFlag = False
edouard@2643:         for baseDataTypeList in self.BaseDataTypes.values():
edouard@2643:             if datatype in baseDataTypeList:
edouard@2643:                 baseTypeFlag = True
edouard@2643:                 break
edouard@2643:         return baseTypeFlag
edouard@2643: 
edouard@2643:     def GetBaseDataType(self, datatype):
edouard@2643:         """
edouard@2643:         Get a base data type corresponding the datatype.
edouard@2643:         @param datatype: Some data type (string format)
edouard@2643:         @return base data type
edouard@2643:         """
edouard@2643:         if self.IsBaseDataType(datatype):
edouard@2643:             return datatype
edouard@2643:         elif not datatype.find("STRING") == -1:
edouard@2643:             return datatype
edouard@2643:         else:
edouard@2643:             datatypes = self.ExtractAllDataTypes()
edouard@2643:             base_datatype = datatypes[datatype].getBaseType()
edouard@2643:             return self.GetBaseDataType(base_datatype)
edouard@2643: 
edouard@2643:     def GetValidDataType(self, datatype):
edouard@2643:         """
edouard@2643:         Convert the datatype into a data type that is possible to download/upload 
edouard@2643:         in etherlab master stack.
edouard@2643:         @param datatype: Some data type (string format)
edouard@2643:         @return base_type: vaild data type
edouard@2643:         """
edouard@2643:         base_type = self.GetBaseDataType(datatype)
edouard@2643: 
edouard@2643:         if re.match("STRING\([0-9]*\)", datatype) is not None:
edouard@2643:             return "string"
edouard@2643:         else:
edouard@2643:             for key, value in self.BaseDataTypes.items():
edouard@2643:                 if base_type in value:
edouard@2643:                     return key
edouard@2643:         return base_type 
edouard@2643: 
edouard@2643:     # Not Used 
edouard@2643:     def GetAllEntriesList(self):
edouard@2643:         """
edouard@2643:         Get All entries information that includes index, sub-index, name,
edouard@2643:         type, bit size, PDO mapping, and default value.
edouard@2643:         @return self.entries: dictionary of entry
edouard@2643:         """
edouard@2643:         slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos())
edouard@2643:         type_infos = slave.getType()
edouard@2643:         device, alignment = self.Controler.CTNParent.GetModuleInfos(type_infos)
edouard@2643:         self.entries = device.GetEntriesList()
edouard@2643:         datatypes = self.ExtractAllDataTypes()
edouard@2643:         objects = self.ExtractObjects()
edouard@2643:         entries_list = self.entries.items()
edouard@2643:         entries_list.sort()
edouard@2643: 
edouard@2643:         # append sub entries
edouard@2643:         for (index, subidx), entry in entries_list:
edouard@2643:             # entry_* is string type
edouard@2643:             entry_type = entry["Type"]
edouard@2643:             entry_index = entry["Index"]
edouard@2643:             
edouard@2643:             try:
edouard@2643:                 object_info = objects[index].getInfo()
edouard@2643:             except:
edouard@2643:                 continue
edouard@2643:             
edouard@2643:             if object_info is not None:
edouard@2643:                 obj_content = object_info.getcontent()
edouard@2643:             
edouard@2643:             typeinfo = datatypes.get(entry_type, None)
edouard@2643:             bitsize = typeinfo.getBitSize()
edouard@2643:             type_content = typeinfo.getcontent()
edouard@2643:            
edouard@2643:             # ArrayInfo type
edouard@2643:             if type_content is not None and type_content["name"] == "ArrayInfo":
edouard@2643:                 for arrayinfo in type_content["value"]:
edouard@2643:                     element_num = arrayinfo.getElements()
edouard@2643:                     first_subidx = arrayinfo.getLBound()
edouard@2643:                     for offset in range(element_num):
edouard@2643:                         new_subidx = int(first_subidx) + offset
edouard@2643:                         entry_subidx = hex(new_subidx)
edouard@2643:                         if obj_content["value"][new_subidx]["name"] == "SubItem":
edouard@2643:                             subitem = obj_content["value"][new_subidx]["value"]
edouard@2643:                             subname = subitem[new_subidx].getName()
edouard@2643:                         if subname is not None:
edouard@2643:                             entry_name = "%s - %s" % \
edouard@2643:                                     (ExtractName(objects[index].getName()), subname)
edouard@2643:                         else:
edouard@2643:                             entry_name = ExtractName(objects[index].getName()) 
edouard@2643:                         self.entries[(index, new_subidx)] = {
edouard@2643:                                 "Index": entry_index,
edouard@2643:                                 "SubIndex": entry_subidx,
edouard@2643:                                 "Name": entry_name,
edouard@2643:                                 "Type": typeinfo.getBaseType(),
edouard@2643:                                 "BitSize": str(bitsize/element_num),
edouard@2643:                                 "Access": entry["Access"],
edouard@2643:                                 "PDOMapping": entry["PDOMapping"]}
edouard@2643:                         try:
edouard@2643:                             value_info = subitem[new_subidx].getInfo().getcontent()\
edouard@2643:                                                             ["value"][0]["value"][0]
edouard@2643:                             self.AppendDefaultValue(index, new_subidx, value_info)
edouard@2643:                         except:
edouard@2643:                             pass
edouard@2643: 
edouard@2643:                 try:
edouard@2643:                     value_info = subitem[subidx].getInfo().getcontent()\
edouard@2643:                                                             ["value"][0]["value"][0]
edouard@2643:                     self.AppendDefaultValue(index, subidx, value_info)
edouard@2643:                 except:
edouard@2643:                     pass
edouard@2643:             
edouard@2643:             # EnumInfo type
edouard@2643:             elif type_content is not None and type_content["name"] == "EnumInfo":
edouard@2643:                 self.entries[(index, subidx)]["EnumInfo"] = {}
edouard@2643:                 
edouard@2643:                 for enuminfo in type_content["value"]:
edouard@2643:                     text = enuminfo.getText()
edouard@2643:                     enum = enuminfo.getEnum()
edouard@2643:                     self.entries[(index, subidx)]["EnumInfo"][str(enum)] = text
edouard@2643: 
edouard@2643:                 self.entries[(index, subidx)]["DefaultValue"] = "0x00" 
edouard@2643:             
edouard@2643:             # another types
edouard@2643:             else:
edouard@2643:                 if subidx == 0x00:
edouard@2643:                     tmp_subidx = 0x00
edouard@2643: 
edouard@2643:                 try:
edouard@2643:                     if obj_content["value"][tmp_subidx]["name"] == "SubItem":
edouard@2643:                         sub_name = entry["Name"].split(" - ")[1]
edouard@2643:                         for num in range(len(obj_content["value"])):
edouard@2643:                             if sub_name == \
edouard@2643:                                     obj_content["value"][num]["value"][num].getName():
edouard@2643:                                 subitem_content = obj_content["value"][tmp_subidx]\
edouard@2643:                                                              ["value"][tmp_subidx]
edouard@2643:                                 value_info = subitem_content.getInfo().getcontent()\
edouard@2643:                                                              ["value"][0]["value"][0]
edouard@2643:                                 tmp_subidx += 1
edouard@2643:                                 break
edouard@2643:                             else:
edouard@2643:                                 value_info = None
edouard@2643:                         
edouard@2643:                     else:
edouard@2643:                         value_info = \
edouard@2643:                                 obj_content["value"][tmp_subidx]["value"][tmp_subidx]
edouard@2643: 
edouard@2643:                     self.AppendDefaultValue(index, subidx, value_info)
edouard@2643: 
edouard@2643:                 except:
edouard@2643:                     pass
edouard@2643: 
edouard@2643:         return self.entries
edouard@2643:                    
edouard@2643:     # Not Used  
edouard@2643:     def AppendDefaultValue(self, index, subidx, value_info=None):
edouard@2643:         """
edouard@2643:         Get the default value from the ESI xml
edouard@2643:         @param index: entry index
edouard@2643:         @param subidx: entry sub index
edouard@2643:         @param value_info: dictionary of infomation about default value
edouard@2643: 
edouard@2643:         """
edouard@2643:         # there is not default value.
edouard@2643:         if value_info == None:
edouard@2643:             return
edouard@2643: 
edouard@2643:         raw_value = value_info["value"]
edouard@2643:         
edouard@2643:         # default value is hex binary type.
edouard@2643:         if value_info["name"]  == "DefaultData":
edouard@2643:             raw_value_bit = list(hex(raw_value).split("0x")[1])
edouard@2643:              
edouard@2643:             datatype = self.GetValidDataType(self.entries[(index, subidx)]["Type"])
edouard@2643:             if datatype is "string" or datatype is "octet_string":
edouard@2643: 
edouard@2643:                 if "L" in raw_value_bit:
edouard@2643:                     raw_value_bit.remove("L")
edouard@2643: 
edouard@2643:                 default_value = "".join(raw_value_bit).decode("hex")
edouard@2643:            
edouard@2643:             elif datatype is "unicode_string":
edouard@2643:                 default_value = "".join(raw_value_bit).decode("hex").\
edouard@2643:                                                            decode("utf-8")
edouard@2643:             
edouard@2643:             else:   
edouard@2643:                 bit_num = len(raw_value_bit)
edouard@2643:                 # padding 
edouard@2643:                 if not bit_num%2 == 0:
edouard@2643:                     raw_value_bit.insert(0, "0")
edouard@2643: 
edouard@2643:                 default_value_bit = []
edouard@2643:             
edouard@2643:                 # little endian -> big endian
edouard@2643:                 for num in range(bit_num):
edouard@2643:                     if num%2 == 0:
edouard@2643:                         default_value_bit.insert(0, raw_value_bit[num])
edouard@2643:                         default_value_bit.insert(1, raw_value_bit[num+1])
edouard@2643:                 
edouard@2643:                 default_value = "0x%s" % "".join(default_value_bit)
edouard@2643: 
edouard@2643:         # default value is string type.
edouard@2643:         # this case is not tested yet.
edouard@2643:         elif value_info["name"] == "DefaultString":
edouard@2643:             default_value = raw_value
edouard@2643: 
edouard@2643:         # default value is Hex or Dec type.
edouard@2643:         elif value_info["name"] == "DefaultValue":
edouard@2643:             default_value = "0x" + hex(ExtractHexDecValue(raw_value))
edouard@2643: 
edouard@2643:         self.entries[(index, subidx)]["DefaultValue"] = default_value
edouard@2643: 
andrej@2356:     # -------------------------------------------------------------------------------
andrej@2354:     #                        Used PDO Monitoring
andrej@2356:     # -------------------------------------------------------------------------------
andrej@2354:     def RequestPDOInfo(self):
andrej@2354:         """
edouard@2643:         Load slave information from RootClass (XML data) and parse the information 
edouard@2643:         (calling SlavePDOData() method).
andrej@2355:         """
andrej@2354:         # Load slave information from ESI XML file (def EthercatMaster.py)
andrej@2354:         slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos())
andrej@2355: 
andrej@2354:         type_infos = slave.getType()
andrej@2406:         device, _alignment = self.Controler.CTNParent.GetModuleInfos(type_infos)
andrej@2354:         # Initialize PDO data set
andrej@2354:         self.ClearDataSet()
andrej@2355: 
andrej@2355:         # if 'device' object is valid, call SavePDOData() to parse PDO data
andrej@2375:         if device is not None:
andrej@2354:             self.SavePDOData(device)
andrej@2355: 
andrej@2354:     def SavePDOData(self, device):
andrej@2354:         """
andrej@2354:         Parse PDO data and store the results in TXPDOCategory and RXPDOCategory
andrej@2354:         Tx(Rx)PDOCategory : index, name, entry number
andrej@2354:         Tx(Rx)Info : entry index, sub index, name, length, type
andrej@2354:         @param device : Slave information extracted from ESI XML file
andrej@2355:         """
andrej@2354:         # Parsing TXPDO entries
andrej@2406:         for pdo, _pdo_info in ([(pdo, "Inputs") for pdo in device.getTxPdo()]):
andrej@2354:             # Save pdo_index, entry, and name of each entry
andrej@2354:             pdo_index = ExtractHexDecValue(pdo.getIndex().getcontent())
andrej@2354:             entries = pdo.getEntry()
andrej@2354:             pdo_name = ExtractName(pdo.getName())
edouard@2643:             excludes = pdo.getExclude()
edouard@2643:             exclude_list = []
edouard@2643:             Sm = pdo.getSm()
edouard@2643: 
edouard@2643:             if excludes :
edouard@2643:                 for exclude in excludes:
edouard@2643:                     exclude_list.append(ExtractHexDecValue(exclude.getcontent()))
andrej@2355: 
andrej@2354:             # Initialize entry number count
andrej@2354:             count = 0
andrej@2355: 
andrej@2354:             # Parse entries
andrej@2354:             for entry in entries:
andrej@2354:                 # Save index and subindex
andrej@2354:                 index = ExtractHexDecValue(entry.getIndex().getcontent())
andrej@2354:                 subindex = ExtractHexDecValue(entry.getSubIndex())
andrej@2354:                 # if entry name exists, save entry data
andrej@2375:                 if ExtractName(entry.getName()) is not None:
andrej@2354:                     entry_infos = {
andrej@2407:                         "entry_index": index,
andrej@2407:                         "subindex": subindex,
andrej@2407:                         "name": ExtractName(entry.getName()),
edouard@2643:                         "bitlen": entry.getBitLen()
andrej@2407:                     }
edouard@2643:                     if entry.getDataType() is not None:
edouard@2643:                         entry_infos["type"] = entry.getDataType().getcontent()
andrej@2354:                     self.TxPDOInfo.append(entry_infos)
andrej@2354:                     count += 1
andrej@2355: 
edouard@2643:             categorys = {"pdo_index" : pdo_index, "name" : pdo_name, "sm" : Sm,
edouard@2643:                          "number_of_entry" : count, "exclude_list" : exclude_list}  
andrej@2354:             self.TxPDOCategory.append(categorys)
andrej@2354: 
andrej@2354:         # Parsing RxPDO entries
andrej@2406:         for pdo, _pdo_info in ([(rxpdo, "Outputs") for rxpdo in device.getRxPdo()]):
andrej@2354:             # Save pdo_index, entry, and name of each entry
andrej@2354:             pdo_index = ExtractHexDecValue(pdo.getIndex().getcontent())
andrej@2354:             entries = pdo.getEntry()
andrej@2354:             pdo_name = ExtractName(pdo.getName())
edouard@2643:             excludes = pdo.getExclude()
edouard@2643:             exclude_list = []
edouard@2643:             Sm = pdo.getSm()
edouard@2643: 
edouard@2643:             if excludes :
edouard@2643:                 for exclude in excludes:
edouard@2643:                     exclude_list.append(ExtractHexDecValue(exclude.getcontent()))
andrej@2355: 
andrej@2354:             # Initialize entry number count
andrej@2355:             count = 0
andrej@2355: 
andrej@2355:             # Parse entries
andrej@2354:             for entry in entries:
andrej@2354:                 # Save index and subindex
andrej@2354:                 index = ExtractHexDecValue(entry.getIndex().getcontent())
andrej@2354:                 subindex = ExtractHexDecValue(entry.getSubIndex())
andrej@2354:                 # if entry name exists, save entry data
andrej@2375:                 if ExtractName(entry.getName()) is not None:
andrej@2354:                     entry_infos = {
andrej@2407:                         "entry_index": index,
andrej@2407:                         "subindex": subindex,
andrej@2407:                         "name": ExtractName(entry.getName()),
edouard@2643:                         "bitlen": str(entry.getBitLen())
andrej@2407:                     }
edouard@2643:                     if entry.getDataType() is not None:
edouard@2643:                         entry_infos["type"] = entry.getDataType().getcontent()
andrej@2354:                     self.RxPDOInfo.append(entry_infos)
andrej@2354:                     count += 1
andrej@2355: 
edouard@2643:             categorys = {"pdo_index" : pdo_index, "name" : pdo_name, "sm" : Sm,
edouard@2643:                          "number_of_entry" : count, "exclude_list" : exclude_list}
edouard@2643:             self.RxPDOCategory.append(categorys) 
andrej@2354: 
andrej@2354:     def GetTxPDOCategory(self):
andrej@2354:         """
andrej@2354:         Get TxPDOCategory data structure (Meta informaton of TxPDO).
andrej@2354:         TxPDOCategorys : index, name, number of entries
andrej@2354:         @return TxPDOCategorys
andrej@2355:         """
andrej@2354:         return self.TxPDOCategory
andrej@2355: 
andrej@2354:     def GetRxPDOCategory(self):
andrej@2354:         """
andrej@2354:         Get RxPDOCategory data structure (Meta information of RxPDO).
andrej@2354:         RxPDOCategorys : index, name, number of entries
andrej@2354:         @return RxPDOCategorys
andrej@2355:         """
andrej@2354:         return self.RxPDOCategory
andrej@2355: 
andrej@2354:     def GetTxPDOInfo(self):
andrej@2354:         """
andrej@2355:         Get TxPDOInfo data structure (Detailed information on TxPDO entries).
andrej@2354:         TxPDOInfos : entry index, sub index, name, length, type
andrej@2354:         @return TxPDOInfos
andrej@2355:         """
andrej@2354:         return self.TxPDOInfo
andrej@2355: 
andrej@2354:     def GetRxPDOInfo(self):
andrej@2354:         """
andrej@2355:         Get RxPDOInfo data structure (Detailed information on RxPDO entries).
andrej@2354:         RxPDOInfos : entry index, sub index, name, length, type
andrej@2354:         @return RxPDOInfos
andrej@2355:         """
andrej@2354:         return self.RxPDOInfo
andrej@2355: 
andrej@2354:     def ClearDataSet(self):
andrej@2354:         """
andrej@2354:         Initialize PDO management data structure.
andrej@2355:         """
edouard@2643:         self.TxPDOInfo = []
edouard@2643:         self.TxPDOCategory = []
edouard@2643:         self.RxPDOInfo = []
edouard@2643:         self.RxPDOCategory = []
andrej@2355: 
andrej@2356:     # -------------------------------------------------------------------------------
andrej@2354:     #                        Used EEPROM Management
andrej@2356:     # -------------------------------------------------------------------------------
andrej@2354:     # Base data types in ETG2000; format = {"Name": "BitSize"}
andrej@2354:     BaseDataTypeDict = {"BOOL": "01",
andrej@2354:                         "SINT": "02",
andrej@2354:                         "INT": "03",
andrej@2354:                         "DINT": "04",
andrej@2354:                         "USINT": "05",
andrej@2354:                         "UINT": "06",
andrej@2354:                         "UDINT": "07",
andrej@2354:                         "REAL": "08",
andrej@2354:                         "INT24": "10",
andrej@2354:                         "LREAL": "11",
andrej@2354:                         "INT40": "12",
andrej@2354:                         "INT48": "13",
andrej@2354:                         "INT56": "14",
andrej@2354:                         "LINT": "15",
andrej@2354:                         "UINT24": "16",
andrej@2354:                         "UINT40": "18",
andrej@2354:                         "UINT48": "19",
andrej@2354:                         "UINT56": "1a",
andrej@2354:                         "ULINT": "1b",
andrej@2354:                         "BITARR8": "2d",
andrej@2354:                         "BITARR16": "2e",
andrej@2354:                         "BITARR32": "2f",
andrej@2354:                         "BIT1": "30",
andrej@2354:                         "BIT2": "31",
andrej@2354:                         "BIT3": "32",
andrej@2354:                         "BIT4": "33",
andrej@2354:                         "BIT5": "34",
andrej@2354:                         "BIT6": "35",
andrej@2354:                         "BIT7": "36",
andrej@2355:                         "BIT8": "37"}
andrej@2355: 
andrej@2354:     def GetSmartViewInfos(self):
andrej@2354:         """
andrej@2354:         Parse XML data for "Smart View" of EEPROM contents.
andrej@2354:         @return smartview_infos : EEPROM contents dictionary
andrej@2355:         """
andrej@2354: 
andrej@2354:         smartview_infos = {"eeprom_size": 128,
andrej@2354:                            "pdi_type": 0,
andrej@2354:                            "device_emulation": "False",
andrej@2354:                            "vendor_id": '0x00000000',
andrej@2354:                            "product_code": '0x00000000',
andrej@2354:                            "revision_no": '0x00000000',
andrej@2354:                            "serial_no": '0x00000000',
andrej@2354:                            "supported_mailbox": "",
andrej@2354:                            "mailbox_bootstrapconf_outstart": '0',
andrej@2354:                            "mailbox_bootstrapconf_outlength": '0',
andrej@2354:                            "mailbox_bootstrapconf_instart": '0',
andrej@2354:                            "mailbox_bootstrapconf_inlength": '0',
andrej@2354:                            "mailbox_standardconf_outstart": '0',
andrej@2354:                            "mailbox_standardconf_outlength": '0',
andrej@2354:                            "mailbox_standardconf_instart": '0',
andrej@2354:                            "mailbox_standardconf_inlength": '0'}
andrej@2355: 
andrej@2354:         slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos())
andrej@2354:         type_infos = slave.getType()
andrej@2406:         device, _alignment = self.Controler.CTNParent.GetModuleInfos(type_infos)
andrej@2354: 
andrej@2354:         # 'device' represents current slave device selected by user
andrej@2354:         if device is not None:
andrej@2354:             for eeprom_element in device.getEeprom().getcontent():
andrej@2354:                 # get EEPROM size; <Device>-<Eeprom>-<ByteSize>
andrej@2354:                 if eeprom_element["name"] == "ByteSize":
andrej@2354:                     smartview_infos["eeprom_size"] = eeprom_element
andrej@2355: 
andrej@2354:                 elif eeprom_element["name"] == "ConfigData":
andrej@2354:                     configData_data = self.DecimalToHex(eeprom_element)
andrej@2354:                     # get PDI type; <Device>-<Eeprom>-<ConfigData> address 0x00
andrej@2354:                     smartview_infos["pdi_type"] = int(configData_data[0:2], 16)
andrej@2354:                     # get state of device emulation; <Device>-<Eeprom>-<ConfigData> address 0x01
andrej@2354:                     if "{:0>8b}".format(int(configData_data[2:4], 16))[7] == '1':
andrej@2354:                         smartview_infos["device_emulation"] = "True"
andrej@2354: 
andrej@2354:                 elif eeprom_element["name"] == "BootStrap":
andrej@2354:                     bootstrap_data = "{:0>16x}".format(eeprom_element)
andrej@2354:                     # get bootstrap configuration; <Device>-<Eeprom>-<BootStrap>
andrej@2355:                     for cfg, iter in [("mailbox_bootstrapconf_outstart", 0),
andrej@2354:                                       ("mailbox_bootstrapconf_outlength", 1),
andrej@2354:                                       ("mailbox_bootstrapconf_instart", 2),
andrej@2354:                                       ("mailbox_bootstrapconf_inlength", 3)]:
andrej@2354:                         smartview_infos[cfg] = str(int(bootstrap_data[4*iter+2:4*(iter+1)]+bootstrap_data[4*iter:4*iter+2], 16))
andrej@2355: 
andrej@2354:             # get protocol (profile) types supported by mailbox; <Device>-<Mailbox>
edouard@2643:             with device.getMailbox() as mb:
edouard@2643:                 if mb is not None:
edouard@2643:                     for mailbox_protocol in mailbox_protocols:
edouard@2643:                         if getattr(mb, "get%s" % mailbox_protocol)() is not None:
edouard@2643:                             smartview_infos["supported_mailbox"] += "%s,  " % mailbox_protocol
andrej@2410:             smartview_infos["supported_mailbox"] = smartview_infos["supported_mailbox"].strip(", ")
andrej@2355: 
andrej@2354:             # get standard configuration of mailbox; <Device>-<Sm>
andrej@2354:             for sm_element in device.getSm():
andrej@2354:                 if sm_element.getcontent() == "MBoxOut":
andrej@2354:                     smartview_infos["mailbox_standardconf_outstart"] = str(ExtractHexDecValue(sm_element.getStartAddress()))
andrej@2354:                     smartview_infos["mailbox_standardconf_outlength"] = str(ExtractHexDecValue(sm_element.getDefaultSize()))
andrej@2354:                 elif sm_element.getcontent() == "MBoxIn":
andrej@2354:                     smartview_infos["mailbox_standardconf_instart"] = str(ExtractHexDecValue(sm_element.getStartAddress()))
andrej@2354:                     smartview_infos["mailbox_standardconf_inlength"] = str(ExtractHexDecValue(sm_element.getDefaultSize()))
andrej@2354:                 else:
andrej@2354:                     pass
andrej@2354: 
andrej@2354:             # get device identity from <Device>-<Type>
edouard@2643:             # vendor ID; by default, pre-defined value in self.ModulesLibrary
edouard@2643:             # if device type in 'vendor' item equals to actual slave device type, set 'vendor_id' to vendor ID.
andrej@2354:             for vendor_id, vendor in self.Controler.CTNParent.CTNParent.ModulesLibrary.Library.iteritems():
andrej@2354:                 for available_device in vendor["groups"][vendor["groups"].keys()[0]]["devices"]:
andrej@2354:                     if available_device[0] == type_infos["device_type"]:
andrej@2354:                         smartview_infos["vendor_id"] = "0x" + "{:0>8x}".format(vendor_id)
andrej@2355: 
edouard@2643:             # product code;
andrej@2354:             if device.getType().getProductCode() is not None:
andrej@2354:                 product_code = device.getType().getProductCode()
andrej@2354:                 smartview_infos["product_code"] = "0x"+"{:0>8x}".format(ExtractHexDecValue(product_code))
andrej@2355: 
edouard@2643:             # revision number;
andrej@2354:             if device.getType().getRevisionNo() is not None:
andrej@2354:                 revision_no = device.getType().getRevisionNo()
andrej@2354:                 smartview_infos["revision_no"] = "0x"+"{:0>8x}".format(ExtractHexDecValue(revision_no))
andrej@2355: 
edouard@2643:             # serial number;
andrej@2354:             if device.getType().getSerialNo() is not None:
andrej@2354:                 serial_no = device.getType().getSerialNo()
andrej@2354:                 smartview_infos["serial_no"] = "0x"+"{:0>8x}".format(ExtractHexDecValue(serial_no))
andrej@2355: 
andrej@2354:             return smartview_infos
andrej@2355: 
andrej@2354:         else:
andrej@2354:             return None
andrej@2355: 
andrej@2354:     def DecimalToHex(self, decnum):
andrej@2354:         """
andrej@2355:         Convert decimal value into hexadecimal representation.
andrej@2354:         @param decnum : decimal value
andrej@2354:         @return hex_data : hexadecimal representation of input value in decimal
andrej@2355:         """
edouard@2643:         value = "%x" % int(decnum, 16)
andrej@2354:         value_len = len(value)
andrej@2354:         if (value_len % 2) == 0:
andrej@2354:             hex_len = value_len
andrej@2354:         else:
andrej@2437:             hex_len = (value_len // 2) * 2 + 2
andrej@2355: 
edouard@2643:         hex_data = ("{:0>"+str(hex_len)+"x}").format(int(decnum, 16))
andrej@2355: 
andrej@2354:         return hex_data
andrej@2354: 
andrej@2354:     def SiiRead(self):
andrej@2354:         """
andrej@2354:         Get slave EEPROM contents maintained by master device using "ethercat sii_read -p %d" command.
andrej@2354:         Command example : "ethercat sii_read -p 0"
andrej@2354:         @return return_val : result of "ethercat sii_read" (binary data)
andrej@2355:         """
andrej@2406:         _error, return_val = self.Controler.RemoteExec(SII_READ % (self.Controler.GetSlavePos()), return_val=None)
andrej@2354:         self.SiiData = return_val
andrej@2354:         return return_val
andrej@2354: 
andrej@2354:     def SiiWrite(self, binary):
andrej@2354:         """
andrej@2354:         Overwrite slave EEPROM contents using "ethercat sii_write -p %d" command.
andrej@2354:         Command example : "ethercat sii_write -p 0 - (binary contents)"
andrej@2354:         @param binary : EEPROM contents in binary data format
andrej@2354:         @return return_val : result of "ethercat sii_write" (If it succeeds, the return value is NULL.)
andrej@2355:         """
andrej@2406:         _error, return_val = self.Controler.RemoteExec(
andrej@2406:             SII_WRITE % (self.Controler.GetSlavePos()),
andrej@2406:             return_val=None,
andrej@2406:             sii_data=binary)
andrej@2355:         return return_val
andrej@2354: 
andrej@2354:     def LoadData(self):
andrej@2354:         """
andrej@2354:         Loading data from EEPROM use Sii_Read Method
andrej@2354:         @return self.BinaryCode : slave EEPROM data in binary format (zero-padded)
andrej@2355:         """
andrej@2354:         return_val = self.Controler.CommonMethod.SiiRead()
andrej@2354:         self.BinaryCode = return_val
andrej@2354:         self.Controler.SiiData = self.BinaryCode
andrej@2354: 
andrej@2354:         # append zero-filled padding data up to EEPROM size
andrej@2406:         for dummy in range(self.SmartViewInfosFromXML["eeprom_size"] - len(self.BinaryCode)):
andrej@2446:             self.BinaryCode = self.BinaryCode + self.HexDecode('ff')[0]
andrej@2355: 
andrej@2354:         return self.BinaryCode
andrej@2354: 
andrej@2354:     def HexRead(self, binary):
andrej@2354:         """
andrej@2354:         Convert binary digit representation into hexadecimal representation for "Hex View" menu.
andrej@2354:         @param binary : binary digits
andrej@2354:         @return hexCode : hexadecimal digits
andrej@2354:         @return hexview_table_row, hexview_table_col : Grid size for "Hex View" UI
andrej@2355:         """
andrej@2354:         row_code = []
andrej@2354:         row_text = ""
andrej@2354:         row = 0
andrej@2354:         hex_code = []
andrej@2354: 
andrej@2354:         hexview_table_col = 17
andrej@2355: 
andrej@2375:         for index in range(0, len(binary)):
andrej@2354:             if len(binary[index]) != 1:
andrej@2354:                 break
andrej@2354:             else:
andrej@2355:                 digithexstr = hex(ord(binary[index]))
andrej@2354: 
andrej@2354:                 tempvar2 = digithexstr[2:4]
andrej@2354:                 if len(tempvar2) == 1:
andrej@2354:                     tempvar2 = "0" + tempvar2
andrej@2355:                 row_code.append(tempvar2)
andrej@2355: 
andrej@2365:                 if int(digithexstr, 16) >= 32 and int(digithexstr, 16) <= 126:
andrej@2354:                     row_text = row_text + chr(int(digithexstr, 16))
andrej@2354:                 else:
andrej@2354:                     row_text = row_text + "."
andrej@2355: 
andrej@2375:                 if index != 0:
andrej@2354:                     if len(row_code) == (hexview_table_col - 1):
andrej@2354:                         row_code.append(row_text)
andrej@2354:                         hex_code.append(row_code)
andrej@2354:                         row_text = ""
andrej@2354:                         row_code = []
andrej@2355:                         row = row + 1
andrej@2355: 
andrej@2354:         hexview_table_row = row
andrej@2355: 
andrej@2354:         return hex_code, hexview_table_row, hexview_table_col
andrej@2355: 
andrej@2354:     def GenerateEEPROMList(self, data, direction, length):
andrej@2354:         """
andrej@2354:         Generate EEPROM data list by reconstructing 'data' string.
andrej@2354:         example : data="12345678", direction=0, length=8 -> eeprom_list=['12', '34', '56', '78']
andrej@2354:                   data="12345678", direction=1, length=8 -> eeprom_list=['78', '56', '34', '12']
andrej@2354:         @param data : string to be reconstructed
andrej@2354:         @param direction : endianness
andrej@2354:         @param length : data length
andrej@2354:         @return eeprom_list : reconstructed list data structure
andrej@2355:         """
andrej@2354:         eeprom_list = []
andrej@2354: 
andrej@2354:         if direction is 0 or 1:
andrej@2437:             for dummy in range(length//2):
andrej@2354:                 if data == "":
andrej@2354:                     eeprom_list.append("00")
andrej@2354:                 else:
andrej@2354:                     eeprom_list.append(data[direction*(length-2):direction*(length-2)+2])
andrej@2354:                 data = data[(1-direction)*2:length-direction*2]
andrej@2354:                 length -= 2
andrej@2354:         return eeprom_list
andrej@2355: 
andrej@2354:     def XmlToEeprom(self):
andrej@2354:         """
andrej@2354:         Extract slave EEPROM contents using slave ESI XML file.
andrej@2354:           - Mandatory parts
andrej@2354:           - String category : ExtractEEPROMStringCategory()
andrej@2354:           - General category : ExtractEEPROMGeneralCategory()
andrej@2354:           - FMMU category : ExtractEEPROMFMMUCategory
andrej@2354:           - SyncM category : ExtractEEPROMSyncMCategory()
andrej@2354:           - Tx/RxPDO category : ExtractEEPROMPDOCategory()
andrej@2354:           - DC category : ExtractEEPROMDCCategory()
andrej@2355:         @return eeprom_binary
andrej@2355:         """
andrej@2354:         eeprom = []
andrej@2354:         data = ""
andrej@2354:         eeprom_size = 0
andrej@2354:         eeprom_binary = ""
andrej@2354: 
andrej@2354:         # 'device' is the slave device of the current EtherCAT slave plugin
andrej@2354:         slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos())
andrej@2354:         type_infos = slave.getType()
andrej@2406:         device, _alignment = self.Controler.CTNParent.GetModuleInfos(type_infos)
andrej@2355: 
andrej@2354:         if device is not None:
andrej@2354:             # get ConfigData for EEPROM offset 0x0000-0x000d; <Device>-<Eeprom>-<ConfigData>
andrej@2354:             for eeprom_element in device.getEeprom().getcontent():
andrej@2354:                 if eeprom_element["name"] == "ConfigData":
andrej@2354:                     data = self.DecimalToHex(eeprom_element)
andrej@2354:             eeprom += self.GenerateEEPROMList(data, 0, 28)
andrej@2355: 
andrej@2354:             # calculate CRC for EEPROM offset 0x000e-0x000f
andrej@2354:             crc = 0x48
andrej@2354:             for segment in eeprom:
andrej@2354:                 for i in range(8):
andrej@2354:                     bit = crc & 0x80
andrej@2354:                     crc = (crc << 1) | ((int(segment, 16) >> (7 - i)) & 0x01)
andrej@2354:                     if bit:
andrej@2355:                         crc ^= 0x07
andrej@2406:             for dummy in range(8):
andrej@2354:                 bit = crc & 0x80
andrej@2354:                 crc <<= 1
andrej@2354:                 if bit:
andrej@2355:                     crc ^= 0x07
andrej@2354:             eeprom.append(hex(crc)[len(hex(crc))-3:len(hex(crc))-1])
andrej@2354:             eeprom.append("00")
andrej@2355: 
andrej@2354:             # get VendorID for EEPROM offset 0x0010-0x0013;
andrej@2354:             data = ""
andrej@2354:             for vendor_id, vendor in self.Controler.CTNParent.CTNParent.ModulesLibrary.Library.iteritems():
andrej@2354:                 for available_device in vendor["groups"][vendor["groups"].keys()[0]]["devices"]:
andrej@2354:                     if available_device[0] == type_infos["device_type"]:
andrej@2354:                         data = "{:0>8x}".format(vendor_id)
andrej@2354:             eeprom += self.GenerateEEPROMList(data, 1, 8)
andrej@2355: 
andrej@2354:             # get Product Code for EEPROM offset 0x0014-0x0017;
andrej@2354:             data = ""
andrej@2354:             if device.getType().getProductCode() is not None:
andrej@2354:                 data = "{:0>8x}".format(ExtractHexDecValue(device.getType().getProductCode()))
andrej@2354:             eeprom += self.GenerateEEPROMList(data, 1, 8)
andrej@2355: 
andrej@2354:             # get Revision Number for EEPROM offset 0x0018-0x001b;
andrej@2354:             data = ""
andrej@2354:             if device.getType().getRevisionNo() is not None:
andrej@2354:                 data = "{:0>8x}".format(ExtractHexDecValue(device.getType().getRevisionNo()))
andrej@2355:             eeprom += self.GenerateEEPROMList(data, 1, 8)
andrej@2355: 
andrej@2354:             # get Serial Number for EEPROM 0x001c-0x001f;
andrej@2354:             data = ""
andrej@2354:             if device.getType().getSerialNo() is not None:
andrej@2354:                 data = "{:0>8x}".format(ExtractHexDecValue(device.getType().getSerialNo()))
andrej@2354:             eeprom += self.GenerateEEPROMList(data, 1, 8)
andrej@2355: 
andrej@2354:             # get Execution Delay for EEPROM 0x0020-0x0021; not analyzed yet
andrej@2354:             eeprom.append("00")
andrej@2354:             eeprom.append("00")
andrej@2355: 
andrej@2354:             # get Port0/1 Delay for EEPROM offset 0x0022-0x0025; not analyzed yet
andrej@2354:             eeprom.append("00")
andrej@2354:             eeprom.append("00")
andrej@2354:             eeprom.append("00")
andrej@2354:             eeprom.append("00")
andrej@2355: 
andrej@2354:             # reserved for EEPROM offset 0x0026-0x0027;
andrej@2354:             eeprom.append("00")
andrej@2354:             eeprom.append("00")
andrej@2354: 
andrej@2354:             # get BootStrap for EEPROM offset 0x0028-0x002e; <Device>-<Eeprom>-<BootStrap>
andrej@2354:             data = ""
andrej@2354:             for eeprom_element in device.getEeprom().getcontent():
andrej@2354:                 if eeprom_element["name"] == "BootStrap":
edouard@2643:                     data = "{:0>16x}".format(int(eeprom_element,16))
andrej@2354:             eeprom += self.GenerateEEPROMList(data, 0, 16)
andrej@2355: 
andrej@2354:             # get Standard Mailbox for EEPROM offset 0x0030-0x0037; <Device>-<sm>
andrej@2354:             data = ""
andrej@2354:             standard_send_mailbox_offset = None
andrej@2354:             standard_send_mailbox_size = None
andrej@2354:             standard_receive_mailbox_offset = None
andrej@2354:             standard_receive_mailbox_size = None
andrej@2354:             for sm_element in device.getSm():
andrej@2354:                 if sm_element.getcontent() == "MBoxOut":
andrej@2354:                     standard_receive_mailbox_offset = "{:0>4x}".format(ExtractHexDecValue(sm_element.getStartAddress()))
andrej@2354:                     standard_receive_mailbox_size = "{:0>4x}".format(ExtractHexDecValue(sm_element.getDefaultSize()))
andrej@2354:                 elif sm_element.getcontent() == "MBoxIn":
andrej@2354:                     standard_send_mailbox_offset = "{:0>4x}".format(ExtractHexDecValue(sm_element.getStartAddress()))
andrej@2354:                     standard_send_mailbox_size = "{:0>4x}".format(ExtractHexDecValue(sm_element.getDefaultSize()))
andrej@2355: 
andrej@2354:             if standard_receive_mailbox_offset is None:
andrej@2354:                 eeprom.append("00")
andrej@2354:                 eeprom.append("00")
andrej@2354:             else:
andrej@2354:                 eeprom.append(standard_receive_mailbox_offset[2:4])
andrej@2354:                 eeprom.append(standard_receive_mailbox_offset[0:2])
andrej@2354:             if standard_receive_mailbox_size is None:
andrej@2354:                 eeprom.append("00")
andrej@2354:                 eeprom.append("00")
andrej@2354:             else:
andrej@2354:                 eeprom.append(standard_receive_mailbox_size[2:4])
andrej@2354:                 eeprom.append(standard_receive_mailbox_size[0:2])
andrej@2354:             if standard_send_mailbox_offset is None:
andrej@2354:                 eeprom.append("00")
andrej@2354:                 eeprom.append("00")
andrej@2354:             else:
andrej@2354:                 eeprom.append(standard_send_mailbox_offset[2:4])
andrej@2354:                 eeprom.append(standard_send_mailbox_offset[0:2])
andrej@2354:             if standard_send_mailbox_size is None:
andrej@2354:                 eeprom.append("00")
andrej@2354:                 eeprom.append("00")
andrej@2354:             else:
andrej@2354:                 eeprom.append(standard_send_mailbox_size[2:4])
andrej@2354:                 eeprom.append(standard_send_mailbox_size[0:2])
andrej@2355: 
andrej@2354:             # get supported mailbox protocols for EEPROM offset 0x0038-0x0039;
andrej@2354:             data = 0
edouard@2643:             with device.getMailbox() as mb:
edouard@2643:                 if mb is not None:
edouard@2643:                     for bit, mbprot in enumerate(mailbox_protocols):
edouard@2643:                         if getattr(mb, "get%s" % mbprot)() is not None:
edouard@2643:                             data += 1 << bit
andrej@2354:             data = "{:0>4x}".format(data)
andrej@2354:             eeprom.append(data[2:4])
andrej@2354:             eeprom.append(data[0:2])
andrej@2355: 
andrej@2354:             # resereved for EEPROM offset 0x003a-0x007b;
andrej@2354:             for i in range(0x007b-0x003a+0x0001):
andrej@2354:                 eeprom.append("00")
andrej@2355: 
andrej@2354:             # get EEPROM size for EEPROM offset 0x007c-0x007d;
edouard@2643:             # Modify by jblee because of update IDE module (minidom -> lxml) 
andrej@2354:             data = ""
edouard@2643:             for eeprom_element in device.getEeprom().getchildren():
edouard@2643:                 if eeprom_element.tag == "ByteSize":
edouard@2643:                     eeprom_size = int(objectify.fromstring(eeprom_element.tostring()).text)
edouard@2643:                     data = "{:0>4x}".format(eeprom_size/1024*8-1)
andrej@2354: 
andrej@2354:             if data == "":
andrej@2354:                 eeprom.append("00")
andrej@2354:                 eeprom.append("00")
andrej@2354:             else:
andrej@2354:                 eeprom.append(data[2:4])
andrej@2354:                 eeprom.append(data[0:2])
andrej@2355: 
andrej@2355:             # Version for EEPROM 0x007e-0x007f;
edouard@2643:             # According to "EtherCAT Slave Device Description(V0.3.0)"
andrej@2354:             eeprom.append("01")
andrej@2354:             eeprom.append("00")
andrej@2355: 
andrej@2354:             # append String Category data
andrej@2354:             for data in self.ExtractEEPROMStringCategory(device):
andrej@2354:                 eeprom.append(data)
andrej@2355: 
andrej@2354:             # append General Category data
andrej@2354:             for data in self.ExtractEEPROMGeneralCategory(device):
andrej@2354:                 eeprom.append(data)
andrej@2355: 
andrej@2354:             # append FMMU Category data
andrej@2354:             for data in self.ExtractEEPROMFMMUCategory(device):
andrej@2354:                 eeprom.append(data)
andrej@2355: 
andrej@2354:             # append SyncM Category data
andrej@2354:             for data in self.ExtractEEPROMSyncMCategory(device):
andrej@2354:                 eeprom.append(data)
andrej@2355: 
andrej@2354:             # append TxPDO Category data
andrej@2354:             for data in self.ExtractEEPROMPDOCategory(device, "TxPdo"):
andrej@2354:                 eeprom.append(data)
andrej@2355: 
andrej@2354:             # append RxPDO Category data
andrej@2354:             for data in self.ExtractEEPROMPDOCategory(device, "RxPdo"):
andrej@2354:                 eeprom.append(data)
andrej@2355: 
andrej@2354:             # append DC Category data
andrej@2354:             for data in self.ExtractEEPROMDCCategory(device):
andrej@2354:                 eeprom.append(data)
andrej@2355: 
andrej@2354:             # append padding
andrej@2354:             padding = eeprom_size-len(eeprom)
andrej@2354:             for i in range(padding):
andrej@2354:                 eeprom.append("ff")
andrej@2355: 
andrej@2354:             # convert binary code
andrej@2354:             for index in range(eeprom_size):
andrej@2446:                 eeprom_binary = eeprom_binary + self.HexDecode(eeprom[index])[0]
andrej@2355: 
andrej@2354:             return eeprom_binary
andrej@2355: 
andrej@2354:     def ExtractEEPROMStringCategory(self, device):
andrej@2354:         """
andrej@2354:         Extract "Strings" category data from slave ESI XML and generate EEPROM image data.
andrej@2354:         @param device : 'device' object in the slave ESI XML
andrej@2354:         @return eeprom : "Strings" category EEPROM image data
andrej@2355:         """
andrej@2354:         eeprom = []
andrej@2354:         self.Strings = []
andrej@2355:         data = ""
andrej@2361:         count = 0        # string counter
andrej@2361:         padflag = False  # padding flag if category length is odd
andrej@2355: 
andrej@2354:         # index information for General Category in EEPROM
andrej@2354:         self.GroupIdx = 0
andrej@2354:         self.ImgIdx = 0
andrej@2354:         self.OrderIdx = 0
andrej@2354:         self.NameIdx = 0
andrej@2355: 
andrej@2355:         # flag for preventing duplicated vendor specific data
andrej@2354:         typeflag = False
andrej@2354:         grouptypeflag = False
andrej@2354:         groupnameflag = False
andrej@2354:         devnameflag = False
andrej@2354:         imageflag = False
andrej@2355: 
andrej@2354:         # vendor specific data
andrej@2354:         #   element1; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Type>
andrej@2354:         #   vendor_specific_data : vendor specific data (binary type)
andrej@2354:         vendor_specific_data = ""
andrej@2354:         #   vendor_spec_strings : list of vendor specific "strings" for preventing duplicated strings
andrej@2354:         vendor_spec_strings = []
andrej@2354:         for element in device.getType().getcontent():
andrej@2354:             data += element
andrej@2434:         if data != "" and isinstance(data, text):
andrej@2355:             for vendor_spec_string in vendor_spec_strings:
andrej@2354:                 if data == vendor_spec_string:
andrej@2354:                     self.OrderIdx = vendor_spec_strings.index(data)+1
andrej@2354:                     typeflag = True
andrej@2354:                     break
andrej@2354:             if typeflag is False:
andrej@2354:                 count += 1
andrej@2354:                 self.Strings.append(data)
andrej@2354:                 vendor_spec_strings.append(data)
andrej@2354:                 typeflag = True
andrej@2354:                 self.OrderIdx = count
andrej@2354:                 vendor_specific_data += "{:0>2x}".format(len(data))
andrej@2354:                 for character in range(len(data)):
andrej@2354:                     vendor_specific_data += "{:0>2x}".format(ord(data[character]))
andrej@2354:         data = ""
andrej@2355: 
edouard@2643:         # element2-1; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<GroupType>
andrej@2354:         data = device.getGroupType()
andrej@2434:         if data is not None and isinstance(data, text):
andrej@2354:             for vendor_spec_string in vendor_spec_strings:
andrej@2354:                 if data == vendor_spec_string:
andrej@2354:                     self.GroupIdx = vendor_spec_strings.index(data)+1
andrej@2354:                     grouptypeflag = True
andrej@2354:                     break
andrej@2354:             if grouptypeflag is False:
andrej@2354:                 count += 1
andrej@2354:                 self.Strings.append(data)
andrej@2354:                 vendor_spec_strings.append(data)
andrej@2354:                 grouptypeflag = True
andrej@2354:                 self.GroupIdx = count
andrej@2354:                 vendor_specific_data += "{:0>2x}".format(len(data))
andrej@2354:                 for character in range(len(data)):
andrej@2354:                     vendor_specific_data += "{:0>2x}".format(ord(data[character]))
andrej@2355: 
andrej@2355:         #  element2-2; <EtherCATInfo>-<Groups>-<Group>-<Type>
andrej@2355:         if grouptypeflag is False:
andrej@2354:             if self.Controler.CTNParent.CTNParent.ModulesLibrary.Library is not None:
andrej@2406:                 for _vendor_id, vendor in self.Controler.CTNParent.CTNParent.ModulesLibrary.Library.iteritems():
andrej@2354:                     for group_type, group_etc in vendor["groups"].iteritems():
andrej@2354:                         for device_item in group_etc["devices"]:
andrej@2355:                             if device == device_item[1]:
andrej@2354:                                 data = group_type
andrej@2434:                 if data is not None and isinstance(data, text):
andrej@2354:                     for vendor_spec_string in vendor_spec_strings:
andrej@2354:                         if data == vendor_spec_string:
andrej@2354:                             self.GroupIdx = vendor_spec_strings.index(data)+1
andrej@2354:                             grouptypeflag = True
andrej@2354:                             break
andrej@2354:                     if grouptypeflag is False:
andrej@2354:                         count += 1
andrej@2354:                         self.Strings.append(data)
andrej@2354:                         vendor_spec_strings.append(data)
andrej@2354:                         grouptypeflag = True
andrej@2354:                         self.GroupIdx = count
andrej@2354:                         vendor_specific_data += "{:0>2x}".format(len(data))
andrej@2354:                         for character in range(len(data)):
andrej@2354:                             vendor_specific_data += "{:0>2x}".format(ord(data[character]))
andrej@2354:         data = ""
andrej@2355: 
andrej@2354:         #  element3; <EtherCATInfo>-<Descriptions>-<Groups>-<Group>-<Name(LcId is "1033")>
andrej@2354:         if self.Controler.CTNParent.CTNParent.ModulesLibrary.Library is not None:
andrej@2406:             for _vendorId, vendor in self.Controler.CTNParent.CTNParent.ModulesLibrary.Library.iteritems():
andrej@2354:                 for group_type, group_etc in vendor["groups"].iteritems():
andrej@2354:                     for device_item in group_etc["devices"]:
andrej@2354:                         if device == device_item[1]:
andrej@2354:                             data = group_etc["name"]
andrej@2434:         if data != "" and isinstance(data, text):
andrej@2354:             for vendor_spec_string in vendor_spec_strings:
andrej@2354:                 if data == vendor_spec_string:
andrej@2354:                     groupnameflag = True
andrej@2354:                     break
andrej@2354:             if groupnameflag is False:
andrej@2354:                 count += 1
andrej@2354:                 self.Strings.append(data)
andrej@2354:                 vendor_spec_strings.append(data)
andrej@2354:                 groupnameflag = True
andrej@2354:                 vendor_specific_data += "{:0>2x}".format(len(data))
andrej@2354:                 for character in range(len(data)):
andrej@2354:                     vendor_specific_data += "{:0>2x}".format(ord(data[character]))
edouard@2643: 
andrej@2354:         data = ""
andrej@2355: 
andrej@2354:         #  element4; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Name(LcId is "1033" or "1"?)>
andrej@2354:         for element in device.getName():
andrej@2365:             if element.getLcId() == 1 or element.getLcId() == 1033:
andrej@2354:                 data = element.getcontent()
andrej@2434:         if data != "" and isinstance(data, text):
andrej@2354:             for vendor_spec_string in vendor_spec_strings:
andrej@2354:                 if data == vendor_spec_string:
andrej@2354:                     self.NameIdx = vendor_spec_strings.index(data)+1
andrej@2354:                     devnameflag = True
andrej@2354:                     break
andrej@2354:             if devnameflag is False:
andrej@2354:                 count += 1
andrej@2354:                 self.Strings.append(data)
andrej@2354:                 vendor_spec_strings.append(data)
andrej@2354:                 devnameflag = True
andrej@2354:                 self.NameIdx = count
andrej@2354:                 vendor_specific_data += "{:0>2x}".format(len(data))
andrej@2354:                 for character in range(len(data)):
andrej@2354:                     vendor_specific_data += "{:0>2x}".format(ord(data[character]))
andrej@2354:         data = ""
andrej@2355: 
andrej@2354:         #  element5-1; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Image16x14>
andrej@2354:         if device.getcontent() is not None:
andrej@2354:             data = device.getcontent()
andrej@2434:             if data is not None and isinstance(data, text):
andrej@2354:                 for vendor_spec_string in vendor_spec_strings:
andrej@2354:                     if data == vendor_spec_string:
andrej@2354:                         self.ImgIdx = vendor_spec_strings.index(data)+1
andrej@2354:                         imageflag = True
andrej@2354:                         break
andrej@2354:                 if imageflag is False:
andrej@2354:                     count += 1
andrej@2354:                     self.Strings.append(data)
andrej@2354:                     vendor_spec_strings.append(data)
andrej@2354:                     imageflag = True
andrej@2354:                     self.ImgIdx = count
andrej@2354:                     vendor_specific_data += "{:0>2x}".format(len(data))
andrej@2354:                     for character in range(len(data)):
andrej@2354:                         vendor_specific_data += "{:0>2x}".format(ord(data[character]))
andrej@2355: 
andrej@2354:         #  element5-2; <EtherCATInfo>-<Descriptions>-<Groups>-<Group>-<Image16x14>
andrej@2354:         if imageflag is False:
andrej@2354:             if self.Controler.CTNParent.CTNParent.ModulesLibrary.Library is not None:
andrej@2406:                 for _vendor_id, vendor in self.Controler.CTNParent.CTNParent.ModulesLibrary.Library.iteritems():
andrej@2354:                     for group_type, group_etc in vendor["groups"].iteritems():
andrej@2354:                         for device_item in group_etc["devices"]:
andrej@2354:                             if device == device_item[1]:
andrej@2354:                                 data = group_etc
andrej@2434:                 if data is not None and isinstance(data, text):
andrej@2354:                     for vendor_spec_string in vendor_spec_strings:
andrej@2354:                         if data == vendor_spec_string:
andrej@2354:                             self.ImgIdx = vendor_spec_strings.index(data)+1
andrej@2354:                             imageflag = True
andrej@2354:                             break
andrej@2354:                     if imageflag is False:
andrej@2354:                         count += 1
andrej@2354:                         self.Strings.append(data)
andrej@2354:                         vendor_spec_strings.append(data)
andrej@2354:                         imageflag = True
andrej@2354:                         self.ImgIdx = count
andrej@2354:                         vendor_specific_data += "{:0>2x}".format(len(data))
andrej@2354:                         for character in range(len(data)):
andrej@2354:                             vendor_specific_data += "{:0>2x}".format(ord(data[character]))
andrej@2354:         data = ""
andrej@2355: 
andrej@2354:         # DC related elements
andrej@2354:         #  <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Dc>-<OpMode>-<Name>
andrej@2354:         dc_related_elements = ""
andrej@2354:         if device.getDc() is not None:
andrej@2354:             for element in device.getDc().getOpMode():
andrej@2354:                 data = element.getName()
andrej@2417:                 if data != "":
andrej@2354:                     count += 1
andrej@2354:                     self.Strings.append(data)
andrej@2354:                     dc_related_elements += "{:0>2x}".format(len(data))
andrej@2354:                     for character in range(len(data)):
andrej@2354:                         dc_related_elements += "{:0>2x}".format(ord(data[character]))
andrej@2354:                     data = ""
andrej@2355: 
andrej@2354:         # Input elements(TxPDO)
andrej@2354:         #  <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<TxPdo>; Name
andrej@2354:         input_elements = ""
andrej@2354:         inputs = []
andrej@2354:         for element in device.getTxPdo():
andrej@2354:             for name in element.getName():
andrej@2354:                 data = name.getcontent()
andrej@2354:             for input in inputs:
andrej@2355:                 if data == input:
andrej@2354:                     data = ""
andrej@2417:             if data != "":
andrej@2354:                 count += 1
andrej@2354:                 self.Strings.append(data)
andrej@2354:                 inputs.append(data)
andrej@2354:                 input_elements += "{:0>2x}".format(len(data))
andrej@2354:                 for character in range(len(data)):
andrej@2354:                     input_elements += "{:0>2x}".format(ord(data[character]))
andrej@2355:                 data = ""
andrej@2354:             for entry in element.getEntry():
andrej@2354:                 for name in entry.getName():
andrej@2354:                     data = name.getcontent()
andrej@2354:                 for input in inputs:
andrej@2355:                     if data == input:
andrej@2354:                         data = ""
andrej@2417:                 if data != "":
andrej@2354:                     count += 1
andrej@2354:                     self.Strings.append(data)
andrej@2354:                     inputs.append(data)
andrej@2354:                     input_elements += "{:0>2x}".format(len(data))
andrej@2354:                     for character in range(len(data)):
andrej@2354:                         input_elements += "{:0>2x}".format(ord(data[character]))
andrej@2354:                     data = ""
andrej@2355: 
andrej@2354:         # Output elements(RxPDO)
andrej@2354:         #  <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<RxPdo>; Name
andrej@2354:         output_elements = ""
andrej@2354:         outputs = []
andrej@2354:         for element in device.getRxPdo():
andrej@2354:             for name in element.getName():
andrej@2354:                 data = name.getcontent()
andrej@2354:             for output in outputs:
andrej@2355:                 if data == output:
andrej@2354:                     data = ""
andrej@2417:             if data != "":
andrej@2354:                 count += 1
andrej@2354:                 self.Strings.append(data)
andrej@2354:                 outputs.append(data)
andrej@2354:                 output_elements += "{:0>2x}".format(len(data))
andrej@2354:                 for character in range(len(data)):
andrej@2354:                     output_elements += "{:0>2x}".format(ord(data[character]))
andrej@2355:                 data = ""
andrej@2354:             for entry in element.getEntry():
andrej@2354:                 for name in entry.getName():
andrej@2354:                     data = name.getcontent()
andrej@2354:                 for output in outputs:
andrej@2355:                     if data == output:
andrej@2354:                         data = ""
andrej@2417:                 if data != "":
andrej@2354:                     count += 1
andrej@2354:                     self.Strings.append(data)
andrej@2354:                     outputs.append(data)
andrej@2354:                     output_elements += "{:0>2x}".format(len(data))
andrej@2354:                     for character in range(len(data)):
andrej@2354:                         output_elements += "{:0>2x}".format(ord(data[character]))
andrej@2355:                     data = ""
andrej@2355: 
andrej@2354:         # form eeprom data
andrej@2354:         #  category header
andrej@2354:         eeprom.append("0a")
andrej@2354:         eeprom.append("00")
andrej@2354:         #  category length (word); 1 word is 4 bytes. "+2" is the length of string's total number
andrej@2354:         length = len(vendor_specific_data + dc_related_elements + input_elements + output_elements) + 2
andrej@2358:         if length % 4 == 0:
andrej@2354:             pass
andrej@2354:         else:
andrej@2365:             length += length % 4
andrej@2354:             padflag = True
andrej@2437:         eeprom.append("{:0>4x}".format(length//4)[2:4])
andrej@2437:         eeprom.append("{:0>4x}".format(length//4)[0:2])
andrej@2354:         #  total numbers of strings
andrej@2354:         eeprom.append("{:0>2x}".format(count))
andrej@2354:         for element in [vendor_specific_data,
andrej@2354:                         dc_related_elements,
andrej@2354:                         input_elements,
andrej@2354:                         output_elements]:
andrej@2437:             for dummy in range(len(element)//2):
andrej@2354:                 if element == "":
andrej@2354:                     eeprom.append("00")
andrej@2354:                 else:
andrej@2354:                     eeprom.append(element[0:2])
andrej@2355:                 element = element[2:len(element)]
andrej@2355:         # padding if length is odd bytes
andrej@2354:         if padflag is True:
andrej@2354:             eeprom.append("ff")
andrej@2355: 
andrej@2354:         return eeprom
andrej@2355: 
andrej@2354:     def ExtractEEPROMGeneralCategory(self, device):
andrej@2354:         """
andrej@2354:         Extract "General" category data from slave ESI XML and generate EEPROM image data.
andrej@2354:         @param device : 'device' object in the slave ESI XML
andrej@2354:         @return eeprom : "Strings" category EEPROM image data
andrej@2355:         """
andrej@2354:         eeprom = []
andrej@2355: 
andrej@2354:         # category header
andrej@2354:         eeprom.append("1e")
andrej@2354:         eeprom.append("00")
andrej@2355: 
andrej@2354:         # category length
andrej@2354:         eeprom.append("10")
andrej@2354:         eeprom.append("00")
andrej@2355: 
andrej@2354:         # word 1 : Group Type index and Image index in STRINGS Category
andrej@2354:         eeprom.append("{:0>2x}".format(self.GroupIdx))
andrej@2354:         eeprom.append("{:0>2x}".format(self.ImgIdx))
andrej@2355: 
andrej@2354:         # word 2 : Device Type index and Device Name index in STRINGS Category
andrej@2354:         eeprom.append("{:0>2x}".format(self.OrderIdx))
andrej@2354:         eeprom.append("{:0>2x}".format(self.NameIdx))
andrej@2355: 
andrej@2354:         # word 3 : Physical Layer Port info. and CoE Details
andrej@2361:         eeprom.append("01")  # Physical Layer Port info - assume 01
andrej@2354:         #  CoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<CoE>
andrej@2361:         coe_details = 1  # sdo enabled
edouard@2643:         with device.getMailbox() as mb
edouard@2643:             if mb is not None:
edouard@2643:                 coe = mb.getCoE()
edouard@2643:                 if coe is not None:
edouard@2643:                     for bit, flag in enumerate(["SdoInfo", "PdoAssign", "PdoConfig",
edouard@2643:                                                 "PdoUpload", "CompleteAccess"]):
edouard@2643:                         if getattr(coe, "get%s" % flag)() is not None:
edouard@2643:                             coe_details += 1 << bit
edouard@2643:             eeprom.append("{:0>2x}".format(coe_details))
edouard@2643: 
edouard@2643:             # word 4 : FoE Details and EoE Details
edouard@2643:             #  FoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<FoE>
edouard@2643:             if mb is not None and mb.getFoE() is not None:
edouard@2643:                 eeprom.append("01")
edouard@2643:             else:
edouard@2643:                 eeprom.append("00")
edouard@2643:             #  EoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<EoE>
edouard@2643:             if mb is not None and mb.getEoE() is not None:
edouard@2643:                 eeprom.append("01")
edouard@2643:             else:
edouard@2643:                 eeprom.append("00")
edouard@2643: 
edouard@2643:             # word 5 : SoE Channels(reserved) and DS402 Channels
edouard@2643:             #  SoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<SoE>
edouard@2643:             if mb is not None and mb.getSoE() is not None:
edouard@2643:                 eeprom.append("01")
edouard@2643:             else:
edouard@2643:                 eeprom.append("00")
edouard@2643:             #  DS402Channels; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<CoE>: DS402Channels
edouard@2643:             ds402ch = False
edouard@2643:             if mb is not None:
edouard@2643:                 coe = mb.getCoE()
edouard@2643:                 if coe is not None:
edouard@2643:                     ds402ch = coe.getDS402Channels()
andrej@2363:         eeprom.append("01" if ds402ch in [True, 1] else "00")
andrej@2355: 
andrej@2354:         # word 6 : SysmanClass(reserved) and Flags
andrej@2361:         eeprom.append("00")  # reserved
andrej@2355:         #  Flags
andrej@2354:         en_safeop = False
andrej@2354:         en_lrw = False
andrej@2374:         if device.getType().getTcCfgModeSafeOp() is True \
andrej@2384:            or device.getType().getTcCfgModeSafeOp() == 1:
andrej@2354:             en_safeop = True
andrej@2374:         if device.getType().getUseLrdLwr() is True \
andrej@2384:            or device.getType().getUseLrdLwr() == 1:
andrej@2354:             en_lrw = True
andrej@2355: 
andrej@2354:         flags = "0b"+"000000"+str(int(en_lrw))+str(int(en_safeop))
andrej@2354:         eeprom.append("{:0>2x}".format(int(flags, 2)))
andrej@2355: 
andrej@2354:         # word 7 : Current On EBus (assume 0x0000)
andrej@2354:         eeprom.append("00")
andrej@2354:         eeprom.append("00")
andrej@2354:         # after word 7; couldn't analyze yet
andrej@2354:         eeprom.append("03")
andrej@2354:         eeprom.append("00")
andrej@2354:         eeprom.append("11")
andrej@2354:         eeprom.append("00")
andrej@2354:         eeprom.append("00")
andrej@2354:         eeprom.append("00")
andrej@2354:         eeprom.append("00")
andrej@2354:         eeprom.append("00")
andrej@2354:         eeprom.append("00")
andrej@2354:         eeprom.append("00")
andrej@2354:         eeprom.append("00")
andrej@2354:         eeprom.append("00")
andrej@2354:         eeprom.append("00")
andrej@2354:         eeprom.append("00")
andrej@2354:         eeprom.append("00")
andrej@2354:         eeprom.append("00")
andrej@2354:         eeprom.append("00")
andrej@2354:         eeprom.append("00")
andrej@2355: 
andrej@2354:         return eeprom
andrej@2355: 
andrej@2354:     def ExtractEEPROMFMMUCategory(self, device):
andrej@2354:         """
andrej@2354:         Extract "FMMU" category data from slave ESI XML and generate EEPROM image data.
andrej@2354:         @param device : 'device' object in the slave ESI XML
andrej@2354:         @return eeprom : "Strings" category EEPROM image data
andrej@2355:         """
andrej@2354:         eeprom = []
andrej@2354:         data = ""
andrej@2361:         count = 0  # number of FMMU
andrej@2354:         padflag = False
andrej@2355: 
andrej@2354:         for fmmu in device.getFmmu():
andrej@2354:             count += 1
andrej@2354:             if fmmu.getcontent() == "Outputs":
andrej@2354:                 data += "01"
andrej@2354:             if fmmu.getcontent() == "Inputs":
andrej@2354:                 data += "02"
andrej@2354:             if fmmu.getcontent() == "MBoxState":
andrej@2354:                 data += "03"
andrej@2355: 
andrej@2354:         # construct of EEPROM data
andrej@2417:         if data != "":
andrej@2354:             #  category header
andrej@2354:             eeprom.append("28")
andrej@2354:             eeprom.append("00")
andrej@2354:             #  category length
andrej@2358:             if count % 2 == 1:
andrej@2354:                 padflag = True
andrej@2437:                 eeprom.append("{:0>4x}".format((count+1)//2)[2:4])
andrej@2437:                 eeprom.append("{:0>4x}".format((count+1)//2)[0:2])
andrej@2355:             else:
andrej@2437:                 eeprom.append("{:0>4x}".format((count)//2)[2:4])
andrej@2437:                 eeprom.append("{:0>4x}".format((count)//2)[0:2])
andrej@2406:             for dummy in range(count):
andrej@2354:                 if data == "":
andrej@2354:                     eeprom.append("00")
andrej@2354:                 else:
andrej@2354:                     eeprom.append(data[0:2])
andrej@2354:                 data = data[2:len(data)]
andrej@2355:             #  padding if length is odd bytes
andrej@2354:             if padflag is True:
andrej@2355:                 eeprom.append("ff")
andrej@2355: 
andrej@2354:         return eeprom
andrej@2355: 
andrej@2354:     def ExtractEEPROMSyncMCategory(self, device):
andrej@2354:         """
andrej@2354:         Extract "SyncM" category data from slave ESI XML and generate EEPROM image data.
andrej@2354:         @param device : 'device' object in the slave ESI XML
andrej@2354:         @return eeprom : "Strings" category EEPROM image data
andrej@2355:         """
andrej@2354:         eeprom = []
andrej@2354:         data = ""
andrej@2363:         number = {"MBoxOut": "01", "MBoxIn": "02", "Outputs": "03", "Inputs": "04"}
andrej@2355: 
andrej@2354:         for sm in device.getSm():
andrej@2354:             for attr in [sm.getStartAddress(),
andrej@2354:                          sm.getDefaultSize(),
andrej@2354:                          sm.getControlByte()]:
andrej@2354:                 if attr is not None:
andrej@2354:                     data += "{:0>4x}".format(ExtractHexDecValue(attr))[2:4]
andrej@2354:                     data += "{:0>4x}".format(ExtractHexDecValue(attr))[0:2]
andrej@2354:                 else:
andrej@2355:                     data += "0000"
andrej@2374:             if sm.getEnable() == "1" or sm.getEnable() is True:
andrej@2354:                 data += "01"
andrej@2354:             else:
andrej@2354:                 data += "00"
andrej@2354:             data += number[sm.getcontent()]
andrej@2355: 
andrej@2417:         if data != "":
andrej@2354:             #  category header
andrej@2354:             eeprom.append("29")
andrej@2354:             eeprom.append("00")
andrej@2355:             #  category length
andrej@2437:             eeprom.append("{:0>4x}".format(len(data)//4)[2:4])
andrej@2437:             eeprom.append("{:0>4x}".format(len(data)//4)[0:2])
andrej@2437:             for dummy in range(len(data)//2):
andrej@2354:                 if data == "":
andrej@2354:                     eeprom.append("00")
andrej@2354:                 else:
andrej@2354:                     eeprom.append(data[0:2])
andrej@2354:                 data = data[2:len(data)]
andrej@2354: 
andrej@2354:         return eeprom
andrej@2355: 
andrej@2354:     def ExtractEEPROMPDOCategory(self, device, pdotype):
andrej@2354:         """
andrej@2354:         Extract ""PDO (Tx, Rx)"" category data from slave ESI XML and generate EEPROM image data.
andrej@2354:         @param device : 'device' object in the slave ESI XML
andrej@2354:         @param pdotype : identifier whether "TxPDO" or "RxPDO".
andrej@2354:         @return eeprom : "Strings" category EEPROM image data
andrej@2355:         """
andrej@2354:         eeprom = []
andrej@2354:         data = ""
andrej@2354:         count = 0
andrej@2354:         en_fixed = False
andrej@2354:         en_mandatory = False
andrej@2354:         en_virtual = False
andrej@2355: 
andrej@2358:         for element in eval("device.get%s()" % pdotype):
andrej@2354:             #  PDO Index
andrej@2354:             data += "{:0>4x}".format(ExtractHexDecValue(element.getIndex().getcontent()))[2:4]
andrej@2354:             data += "{:0>4x}".format(ExtractHexDecValue(element.getIndex().getcontent()))[0:2]
andrej@2354:             #  Number of Entries
andrej@2354:             data += "{:0>2x}".format(len(element.getEntry()))
andrej@2354:             #  About Sync Manager
andrej@2354:             if element.getSm() is not None:
andrej@2354:                 data += "{:0>2x}".format(element.getSm())
andrej@2354:             else:
andrej@2354:                 data += "ff"
andrej@2354:             #  Reference to DC Synch (according to ET1100 documentation) - assume 0
andrej@2354:             data += "00"
andrej@2354:             #  Name Index
andrej@2354:             objname = ""
andrej@2354:             for name in element.getName():
andrej@2354:                 objname = name.getcontent()
andrej@2354:             for name in self.Strings:
andrej@2354:                 count += 1
andrej@2354:                 if objname == name:
andrej@2354:                     break
andrej@2354:             if len(self.Strings)+1 == count:
andrej@2354:                 data += "00"
andrej@2354:             else:
andrej@2354:                 data += "{:0>2x}".format(count)
andrej@2354:             count = 0
andrej@2354:             #  Flags; by Fixed, Mandatory, Virtual attributes ?
andrej@2374:             if element.getFixed() is True or 1:
andrej@2354:                 en_fixed = True
andrej@2374:             if element.getMandatory() is True or 1:
andrej@2354:                 en_mandatory = True
andrej@2374:             if element.getVirtual() is True or element.getVirtual():
andrej@2354:                 en_virtual = True
andrej@2354:             data += str(int(en_fixed)) + str(int(en_mandatory)) + str(int(en_virtual)) + "0"
andrej@2355: 
andrej@2354:             for entry in element.getEntry():
andrej@2354:                 #   Entry Index
andrej@2354:                 data += "{:0>4x}".format(ExtractHexDecValue(entry.getIndex().getcontent()))[2:4]
andrej@2354:                 data += "{:0>4x}".format(ExtractHexDecValue(entry.getIndex().getcontent()))[0:2]
andrej@2354:                 #   Subindex
andrej@2354:                 data += "{:0>2x}".format(int(entry.getSubIndex()))
andrej@2354:                 #   Entry Name Index
andrej@2354:                 objname = ""
andrej@2354:                 for name in entry.getName():
andrej@2354:                     objname = name.getcontent()
andrej@2354:                 for name in self.Strings:
andrej@2354:                     count += 1
andrej@2354:                     if objname == name:
andrej@2354:                         break
andrej@2354:                 if len(self.Strings)+1 == count:
andrej@2354:                     data += "00"
andrej@2354:                 else:
andrej@2354:                     data += "{:0>2x}".format(count)
andrej@2354:                 count = 0
andrej@2354:                 #   DataType
andrej@2354:                 if entry.getDataType() is not None:
andrej@2354:                     if entry.getDataType().getcontent() in self.BaseDataTypeDict:
andrej@2354:                         data += self.BaseDataTypeDict[entry.getDataType().getcontent()]
andrej@2354:                     else:
andrej@2354:                         data += "00"
andrej@2354:                 else:
andrej@2354:                     data += "00"
andrej@2354:                 #   BitLen
andrej@2354:                 if entry.getBitLen() is not None:
andrej@2354:                     data += "{:0>2x}".format(int(entry.getBitLen()))
andrej@2354:                 else:
andrej@2354:                     data += "00"
andrej@2354:                 #   Flags; by Fixed attributes ?
andrej@2354:                 en_fixed = False
andrej@2374:                 if entry.getFixed() is True or entry.getFixed() == 1:
andrej@2354:                     en_fixed = True
andrej@2354:                 data += str(int(en_fixed)) + "000"
andrej@2355: 
andrej@2417:         if data != "":
andrej@2354:             #  category header
andrej@2354:             if pdotype == "TxPdo":
andrej@2354:                 eeprom.append("32")
andrej@2354:             elif pdotype == "RxPdo":
andrej@2354:                 eeprom.append("33")
andrej@2354:             else:
andrej@2354:                 eeprom.append("00")
andrej@2354:             eeprom.append("00")
andrej@2355:             #  category length
andrej@2437:             eeprom.append("{:0>4x}".format(len(data)//4)[2:4])
andrej@2437:             eeprom.append("{:0>4x}".format(len(data)//4)[0:2])
andrej@2354:             data = str(data.lower())
andrej@2437:             for dummy in range(len(data)//2):
andrej@2354:                 if data == "":
andrej@2354:                     eeprom.append("00")
andrej@2354:                 else:
andrej@2354:                     eeprom.append(data[0:2])
andrej@2354:                 data = data[2:len(data)]
andrej@2355: 
andrej@2354:         return eeprom
andrej@2355: 
andrej@2354:     def ExtractEEPROMDCCategory(self, device):
andrej@2354:         """
andrej@2354:         Extract "DC(Distributed Clock)" category data from slave ESI XML and generate EEPROM image data.
andrej@2354:         @param device : 'device' object in the slave ESI XML
andrej@2354:         @return eeprom : "Strings" category EEPROM image data
andrej@2355:         """
andrej@2354:         eeprom = []
andrej@2354:         data = ""
andrej@2354:         count = 0
andrej@2354:         namecount = 0
andrej@2355: 
andrej@2354:         if device.getDc() is not None:
andrej@2354:             for element in device.getDc().getOpMode():
andrej@2354:                 count += 1
andrej@2354:                 #  assume that word 1-7 are 0x0000
andrej@2354:                 data += "0000"
andrej@2354:                 data += "0000"
andrej@2354:                 data += "0000"
andrej@2354:                 data += "0000"
andrej@2354:                 data += "0000"
andrej@2354:                 data += "0000"
andrej@2354:                 data += "0000"
andrej@2354:                 #  word 8-10
andrej@2354:                 #  AssignActivate
andrej@2354:                 if element.getAssignActivate() is not None:
andrej@2354:                     data += "{:0>4x}".format(ExtractHexDecValue(element.getAssignActivate()))[2:4]
andrej@2354:                     data += "{:0>4x}".format(ExtractHexDecValue(element.getAssignActivate()))[0:2]
andrej@2354:                 else:
andrej@2354:                     data += "0000"
andrej@2354:                 #  Factor of CycleTimeSync0 ? and default is 1?
andrej@2354:                 if element.getCycleTimeSync0() is not None:
andrej@2354:                     if element.getCycleTimeSync0().getFactor() is not None:
andrej@2354:                         data += "{:0>2x}".format(int(element.getCycleTimeSync0().getFactor()))
andrej@2354:                         data += "00"
andrej@2354:                     else:
andrej@2354:                         data += "0100"
andrej@2354:                 else:
andrej@2354:                     data += "0100"
andrej@2354:                 #  Index of Name in STRINGS Category
andrej@2354:                 #  Name Index
andrej@2354:                 objname = ""
andrej@2354:                 for name in element.getName():
andrej@2354:                     objname += name
andrej@2354:                 for name in self.Strings:
andrej@2354:                     namecount += 1
andrej@2354:                     if objname == name:
andrej@2354:                         break
andrej@2354:                 if len(self.Strings)+1 == namecount:
andrej@2354:                     data += "00"
andrej@2354:                 else:
andrej@2354:                     data += "{:0>2x}".format(namecount)
andrej@2354:                 namecount = 0
andrej@2354:                 data += "00"
andrej@2354:                 #  assume that word 11-12 are 0x0000
andrej@2354:                 data += "0000"
andrej@2354:                 data += "0000"
andrej@2355: 
andrej@2417:         if data != "":
andrej@2354:             #  category header
andrej@2354:             eeprom.append("3c")
andrej@2354:             eeprom.append("00")
andrej@2355:             #  category length
andrej@2437:             eeprom.append("{:0>4x}".format(len(data)//4)[2:4])
andrej@2437:             eeprom.append("{:0>4x}".format(len(data)//4)[0:2])
andrej@2354:             data = str(data.lower())
andrej@2437:             for dummy in range(len(data)//2):
andrej@2354:                 if data == "":
andrej@2354:                     eeprom.append("00")
andrej@2354:                 else:
andrej@2354:                     eeprom.append(data[0:2])
andrej@2354:                 data = data[2:len(data)]
andrej@2355: 
andrej@2354:         return eeprom
andrej@2355: 
andrej@2356:     # -------------------------------------------------------------------------------
andrej@2354:     #                        Used Register Access
andrej@2356:     # -------------------------------------------------------------------------------
andrej@2354:     def RegRead(self, offset, length):
andrej@2354:         """
andrej@2354:         Read slave ESC register content using "ethercat reg_read -p %d %s %s" command.
andrej@2354:         Command example : "ethercat reg_read -p 0 0x0c00 0x0400"
andrej@2354:         @param offset : register address
andrej@2354:         @param length : register length
andrej@2354:         @return return_val : register data
andrej@2355:         """
andrej@2406:         _error, return_val = self.Controler.RemoteExec(
andrej@2406:             REG_READ % (self.Controler.GetSlavePos(), offset, length),
andrej@2406:             return_val=None)
andrej@2355:         return return_val
andrej@2355: 
edouard@2643:     def MultiRegRead(self, slave_num, reg_infos):
edouard@2643:         """
edouard@2643:         
edouard@2643:         @slave_num:
edouard@2643:         @param addr_info:
edouard@2643:         @return return_val: 
edouard@2643:         """
edouard@2643:         reg_info_str = ""
edouard@2643:         for reg_info in reg_infos:
edouard@2643:             reg_info_str = reg_info_str + "%s|" % reg_info
edouard@2643:         reg_info_str = reg_info_str.strip("|")
edouard@2643: 
edouard@2643:         _error, return_val = self.Controler.RemoteExec(\
edouard@2643:             MULTI_REG_READ%(slave_num, reg_info_str),
edouard@2643:             return_val = None)
edouard@2643:         
edouard@2643:         return return_val
edouard@2643:     
andrej@2354:     def RegWrite(self, address, data):
andrej@2354:         """
andrej@2354:         Write data to slave ESC register using "ethercat reg_write -p %d %s %s" command.
andrej@2354:         Command example : "ethercat reg_write -p 0 0x0c04 0x0001"
andrej@2354:         @param address : register address
andrej@2354:         @param data : data to write
andrej@2354:         @return return_val : the execution result of "ethercat reg_write" (for error check)
andrej@2355:         """
andrej@2406:         _error, return_val = self.Controler.RemoteExec(
andrej@2406:             REG_WRITE % (self.Controler.GetSlavePos(), address, data),
andrej@2406:             return_val=None)
andrej@2355:         return return_val
andrej@2355: 
andrej@2354:     def Rescan(self):
andrej@2354:         """
andrej@2354:         Synchronize EEPROM data in master controller with the data in slave device after EEPROM write.
andrej@2354:         Command example : "ethercat rescan -p 0"
andrej@2355:         """
andrej@2406:         _error, _return_val = self.Controler.RemoteExec(RESCAN % (self.Controler.GetSlavePos()), return_val=None)
andrej@2355: 
andrej@2356:     # -------------------------------------------------------------------------------
edouard@2643:     #                        Used DC Configuration
edouard@2643:     #-------------------------------------------------------------------------------
edouard@2643:     def LoadESIData(self):
edouard@2643:         return_data = []
edouard@2643:         slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos())
edouard@2643:         type_infos = slave.getType()
edouard@2643:         device, alignment = self.Controler.CTNParent.GetModuleInfos(type_infos)
edouard@2643:         if device.getDc() is not None:
edouard@2643:             for OpMode in device.getDc().getOpMode():
edouard@2643:                 temp_data = {
edouard@2643:                     "desc" : OpMode.getDesc() if OpMode.getDesc() is not None else "Unused",
edouard@2643:                     "assign_activate" : OpMode.getAssignActivate() \
edouard@2643:                         if OpMode.getAssignActivate() is not None else "#x0000",
edouard@2643:                     "cycletime_sync0" : OpMode.getCycleTimeSync0().getcontent() \
edouard@2643:                         if OpMode.getCycleTimeSync0() is not None else None,
edouard@2643:                     "shifttime_sync0" : OpMode.getShiftTimeSync0().getcontent() \
edouard@2643:                         if OpMode.getShiftTimeSync0() is not None else None,
edouard@2643:                     "cycletime_sync1" : OpMode.getShiftTimeSync1().getcontent() \
edouard@2643:                         if OpMode.getShiftTimeSync1() is not None else None,
edouard@2643:                     "shifttime_sync1" : OpMode.getShiftTimeSync1().getcontent() \
edouard@2643:                         if OpMode.getShiftTimeSync1() is not None else None
edouard@2643:                 }
edouard@2643: 
edouard@2643:                 if OpMode.getCycleTimeSync0() is not None:
edouard@2643:                     temp_data["cycletime_sync0_factor"] = OpMode.getCycleTimeSync0().getFactor()
edouard@2643: 
edouard@2643:                 if OpMode.getCycleTimeSync1() is not None:
edouard@2643:                     temp_data["cycletime_sync1_factor"] = OpMode.getCycleTimeSync1().getFactor()
edouard@2643: 
edouard@2643:                 return_data.append(temp_data)
edouard@2643: 
edouard@2643:         return return_data
edouard@2643:     
edouard@2643:     #-------------------------------------------------------------------------------
andrej@2354:     #                        Common Use Methods
andrej@2356:     # -------------------------------------------------------------------------------
andrej@2354:     def CheckConnect(self, cyclic_flag):
andrej@2354:         """
andrej@2355:         Check connection status (1) between Beremiz and the master (2) between the master and the slave.
andrej@2354:         @param cyclic_flag: 0 - one shot, 1 - periodic
andrej@2354:         @return True or False
andrej@2355:         """
andrej@2354:         if self.Controler.GetCTRoot()._connector is not None:
andrej@2355:             # Check connection between the master and the slave.
andrej@2354:             # Command example : "ethercat xml -p 0"
andrej@2406:             _error, return_val = self.Controler.RemoteExec(SLAVE_XML % (self.Controler.GetSlavePos()), return_val=None)
andrej@2354:             number_of_lines = return_val.split("\n")
andrej@2375:             if len(number_of_lines) <= 2:  # No slave connected to the master controller
andrej@2375:                 if not cyclic_flag:
andrej@2423:                     self.CreateErrorDialog(_('No connected slaves'))
andrej@2354:                 return False
andrej@2355: 
andrej@2375:             elif len(number_of_lines) > 2:
andrej@2354:                 return True
andrej@2355:         else:
andrej@2354:             # The master controller is not connected to Beremiz host
andrej@2375:             if not cyclic_flag:
andrej@2423:                 self.CreateErrorDialog(_('PLC not connected!'))
andrej@2354:             return False
andrej@2355: 
andrej@2354:     def CreateErrorDialog(self, mention):
andrej@2354:         """
andrej@2354:         Create a dialog to indicate error or warning.
andrej@2354:         @param mention : Error String
andrej@2355:         """
andrej@2354:         app_frame = self.Controler.GetCTRoot().AppFrame
andrej@2382:         dlg = wx.MessageDialog(app_frame, mention,
andrej@2423:                                _(' Warning...'),
andrej@2382:                                wx.OK | wx.ICON_INFORMATION)
andrej@2354:         dlg.ShowModal()
andrej@2355:         dlg.Destroy()