Edouard@2152: #!/usr/bin/env python
Edouard@2152: # -*- coding: utf-8 -*-
Edouard@2152: 
edouard@2165: 
edouard@2165: # This file is part of Beremiz
Edouard@2152: #
edouard@2165: # Copyright (C) 2013: Real-Time & Embedded Systems (RTES) Lab. University of Seoul, Korea
Edouard@2152: #
edouard@2165: # See COPYING file for copyrights details.
Edouard@2152: 
Edouard@2152: import os
Edouard@2152: import wx
Edouard@2152: 
Edouard@2163: mailbox_protocols =  ["AoE", "EoE", "CoE", "FoE", "SoE", "VoE"]
Edouard@2163: 
Edouard@2152: def ExtractHexDecValue(value):
Edouard@2152:     """
Edouard@2152:      convert numerical value in string format into decimal or hex format.
Edouard@2152:      @param value : hex or decimal data
Edouard@2152:      @return integer data
Edouard@2152:     """
Edouard@2152:     try:
Edouard@2152:         return int(value)
Edouard@2152:     except:
Edouard@2152:         pass
Edouard@2152:     try:
Edouard@2152:         return int(value.replace("#", "0"), 16)
Edouard@2152:         
Edouard@2152:     except:
Edouard@2152:         raise ValueError, "Invalid value for HexDecValue \"%s\"" % value
Edouard@2152: 
Edouard@2152: def ExtractName(names, default=None):
Edouard@2152:     """
Edouard@2152:      Extract "name" field from XML entries.
Edouard@2152:      @param names : XML entry
Edouard@2152:      @default : if it fails to extract from the designated XML entry, return the default value ("None").
Edouard@2152:      @return default or the name extracted
Edouard@2152:     """
Edouard@2152:     if len(names) == 1:
Edouard@2152:         return names[0].getcontent()
Edouard@2152:     else:
Edouard@2152:         for name in names:
Edouard@2152:             if name.getLcId() == 1033:
Edouard@2152:                 return name.getcontent()
Edouard@2152:     return default
Edouard@2152: 
Edouard@2152: #--------------------------------------------------
Edouard@2152: #         Remote Exec Etherlab Commands
Edouard@2152: #--------------------------------------------------
Edouard@2152: 
Edouard@2152: # --------------------- for master ---------------------------
Edouard@2152: MASTER_STATE = """
Edouard@2152: import commands
Edouard@2152: result = commands.getoutput("ethercat master")
Edouard@2152: returnVal =result 
Edouard@2152: """
Edouard@2152: 
Edouard@2152: # --------------------- for slave ----------------------------
Edouard@2152: # ethercat state -p (slave position) (state (INIT, PREOP, SAFEOP, OP))
Edouard@2152: SLAVE_STATE = """
Edouard@2152: import commands
Edouard@2152: result = commands.getoutput("ethercat state -p %d %s")
Edouard@2152: returnVal = result 
Edouard@2152: """
Edouard@2152: 
Edouard@2152: # ethercat slave
Edouard@2152: GET_SLAVE = """
Edouard@2152: import commands
Edouard@2152: result = commands.getoutput("ethercat slaves")
Edouard@2152: returnVal =result 
Edouard@2152: """
Edouard@2152: 
Edouard@2152: # ethercat xml -p (slave position)
Edouard@2152: SLAVE_XML = """
Edouard@2152: import commands
Edouard@2152: result = commands.getoutput("ethercat xml -p %d")
Edouard@2152: returnVal = result 
Edouard@2152: """
Edouard@2152: 
Edouard@2152: # ethercat sdos -p (slave position)
Edouard@2152: SLAVE_SDO = """
Edouard@2152: import commands
Edouard@2152: result = commands.getoutput("ethercat sdos -p %d")
Edouard@2152: returnVal =result 
Edouard@2152: """
Edouard@2152: 
Edouard@2152: # ethercat upload -p (slave position) (main index) (sub index)
Edouard@2152: GET_SLOW_SDO = """
Edouard@2152: import commands
Edouard@2152: result = commands.getoutput("ethercat upload -p %d %s %s")
Edouard@2152: returnVal =result 
Edouard@2152: """
Edouard@2152: 
Edouard@2152: # ethercat download -p (slave position) (main index) (sub index) (value)
Edouard@2152: SDO_DOWNLOAD = """
Edouard@2152: import commands
Edouard@2152: result = commands.getoutput("ethercat download --type %s -p %d %s %s %s")
Edouard@2152: returnVal =result 
Edouard@2152: """
Edouard@2152: 
Edouard@2152: # ethercat sii_read -p (slave position)
Edouard@2152: SII_READ = """
Edouard@2152: import commands
Edouard@2152: result = commands.getoutput("ethercat sii_read -p %d")
Edouard@2152: returnVal =result 
Edouard@2152: """
Edouard@2152: 
Edouard@2152: # ethercat reg_read -p (slave position) (address) (size)
Edouard@2152: REG_READ = """
Edouard@2152: import commands
Edouard@2152: result = commands.getoutput("ethercat reg_read -p %d %s %s")
Edouard@2152: returnVal =result 
Edouard@2152: """
Edouard@2152: 
Edouard@2152: # ethercat sii_write -p (slave position) - (contents)
Edouard@2152: SII_WRITE = """ 
Edouard@2152: import subprocess 
Edouard@2152: process = subprocess.Popen(
Edouard@2152:     ["ethercat", "-f", "sii_write", "-p", "%d", "-"],
Edouard@2152:     stdin=subprocess.PIPE)
Edouard@2152: process.communicate(sii_data)
Edouard@2152: returnVal = process.returncode 
Edouard@2152: """
Edouard@2152: 
Edouard@2152: # ethercat reg_write -p (slave position) -t (uinit16) (address) (data)
Edouard@2152: REG_WRITE = """ 
Edouard@2152: import commands
Edouard@2152: result = commands.getoutput("ethercat reg_write -p %d -t uint16 %s %s")
Edouard@2152: returnVal =result 
Edouard@2152: """ 
Edouard@2152: 
Edouard@2152: # ethercat rescan -p (slave position)
Edouard@2152: RESCAN = """ 
Edouard@2152: import commands
Edouard@2152: result = commands.getoutput("ethercat rescan -p %d")
Edouard@2152: returnVal =result 
Edouard@2152: """
Edouard@2152: 
Edouard@2152: #--------------------------------------------------
Edouard@2152: #    Common Method For EtherCAT Management 
Edouard@2152: #--------------------------------------------------
Edouard@2152: class _CommonSlave:
Edouard@2152: 
Edouard@2152:     # ----- Data Structure for ethercat management ----
Edouard@2152:     SlaveState = ""
Edouard@2152: 
Edouard@2152:     # category of SDO data
Edouard@2152:     DatatypeDescription, CommunicationObject, ManufacturerSpecific, \
Edouard@2152:     ProfileSpecific, Reserved, AllSDOData = range(6)
Edouard@2152:     
Edouard@2152:     # store the execution result of "ethercat sdos" command into SaveSDOData.
Edouard@2152:     SaveSDOData = []
Edouard@2152:     
Edouard@2152:     # Flags for checking "write" permission of OD entries 
Edouard@2152:     CheckPREOP = False
Edouard@2152:     CheckSAFEOP = False
Edouard@2152:     CheckOP = False
Edouard@2152: 
Edouard@2152:     # Save PDO Data
Edouard@2152:     TxPDOInfo = []
Edouard@2152:     TxPDOCategory = []
Edouard@2152:     RxPDOInfo = []
Edouard@2152:     RxPDOCategory = []
Edouard@2152:     
Edouard@2152:     # Save EEPROM Data
Edouard@2152:     SiiData = ""
Edouard@2152: 
Edouard@2152:     # Save Register Data
Edouard@2152:     RegData = ""
Edouard@2152:     CrtRegSpec = {"ESCType": "",
Edouard@2152:                   "FMMUNumber": "",
Edouard@2152:                   "SMNumber": "",
Edouard@2152:                   "PDIType": ""}
Edouard@2152:     
Edouard@2152:     def __init__(self, controler):
Edouard@2152:         """
Edouard@2152:         Constructor
Edouard@2152:         @param controler: _EthercatSlaveCTN class in EthercatSlave.py
Edouard@2152:         """
Edouard@2152:         self.Controler = controler
Edouard@2152:          
Edouard@2152:         self.ClearSDODataSet()
Edouard@2152:     
Edouard@2152:     #-------------------------------------------------------------------------------
Edouard@2152:     #                        Used Master State
Edouard@2152:     #-------------------------------------------------------------------------------
Edouard@2152:     def GetMasterState(self):
Edouard@2152:         """
Edouard@2152:         Execute "ethercat master" command and parse the execution result
Edouard@2152:         @return MasterState 
Edouard@2152:         """
Edouard@2152: 
Edouard@2152:         # exectute "ethercat master" command 
Edouard@2152:         error, return_val = self.Controler.RemoteExec(MASTER_STATE, return_val = None)
Edouard@2152:         master_state = {}
Edouard@2152:         # parse the reslut
Edouard@2152:         for each_line in return_val.splitlines():
Edouard@2152:             if len(each_line) > 0 :
Edouard@2152:                 chunks = each_line.strip().split(':', 1)
Edouard@2152:                 key = chunks[0]
Edouard@2152:                 value = []
Edouard@2152:                 if len(chunks) > 1 :
Edouard@2152:                     value = chunks[1].split()
Edouard@2152:                 if '(attached)' in value:
Edouard@2152:                     value.remove('(attached)')
Edouard@2152:                 master_state[key] = value
Edouard@2152:          
Edouard@2152:         return master_state     
Edouard@2152:     
Edouard@2152:     #-------------------------------------------------------------------------------
Edouard@2152:     #                        Used Slave State
Edouard@2152:     #-------------------------------------------------------------------------------
Edouard@2152:     def RequestSlaveState(self, command):
Edouard@2152:         """
Edouard@2152:         Set slave state to the specified one using "ethercat states -p %d %s" command.
Edouard@2152:         Command example : "ethercat states -p 0 PREOP" (target slave position and target state are given.)
Edouard@2152:         @param command : target slave state 
Edouard@2152:         """
Edouard@2152:         error, return_val = self.Controler.RemoteExec(SLAVE_STATE%(self.Controler.GetSlavePos(), command), return_val = None)
Edouard@2152:     
Edouard@2152:     def GetSlaveStateFromSlave(self):  
Edouard@2152:         """
Edouard@2152:         Get slave information using "ethercat slaves" command and store the information into internal data structure 
Edouard@2152:         (self.SlaveState) for "Slave State" 
Edouard@2152:         return_val example : 0  0:0  PREOP  +  EL9800 (V4.30) (PIC24, SPI, ET1100)
Edouard@2152:         """ 
Edouard@2152:         error, return_val = self.Controler.RemoteExec(GET_SLAVE, return_val = None)
Edouard@2152:         self.SlaveState = return_val
Edouard@2152:         return return_val 
Edouard@2152: 
Edouard@2152:     #-------------------------------------------------------------------------------
Edouard@2152:     #                        Used SDO Management
Edouard@2152:     #-------------------------------------------------------------------------------
Edouard@2152:     def GetSlaveSDOFromSlave(self):
Edouard@2152:         """
Edouard@2152:         Get SDO objects information of current slave using "ethercat sdos -p %d" command.
Edouard@2152:         Command example : "ethercat sdos -p 0"
Edouard@2152:         @return return_val : execution results of "ethercat sdos" command (need to be parsed later)
Edouard@2152:         """  
Edouard@2152:         error, return_val = self.Controler.RemoteExec(SLAVE_SDO%(self.Controler.GetSlavePos()), return_val = None)
Edouard@2152:         return return_val   
Edouard@2152:         
Edouard@2152:     def SDODownload(self, data_type, idx, sub_idx, value):
Edouard@2152:         """
Edouard@2152:         Set an SDO object value to user-specified value using "ethercat download" command.
Edouard@2152:         Command example : "ethercat download --type int32 -p 0 0x8020 0x12 0x00000000"
Edouard@2152:         @param data_type : data type of SDO entry
Edouard@2152:         @param idx : index of the SDO entry
Edouard@2152:         @param sub_idx : subindex of the SDO entry
Edouard@2152:         @param value : value of SDO entry
Edouard@2152:         """  
Edouard@2152:         error, return_val = self.Controler.RemoteExec(SDO_DOWNLOAD%(data_type, self.Controler.GetSlavePos(), idx, sub_idx, value), return_val = None)
Edouard@2152:     
Edouard@2152:     def BackupSDODataSet(self):
Edouard@2152:         """
Edouard@2152:         Back-up current SDO entry information to restore the SDO data 
Edouard@2152:          in case that the user cancels SDO update operation.
Edouard@2152:     	"""  
Edouard@2152:         self.BackupDatatypeDescription = self.SaveDatatypeDescription
Edouard@2152:         self.BackupCommunicationObject = self.SaveCommunicationObject
Edouard@2152:         self.BackupManufacturerSpecific = self.SaveManufacturerSpecific
Edouard@2152:         self.BackupProfileSpecific = self.SaveProfileSpecific
Edouard@2152:         self.BackupReserved = self.SaveReserved
Edouard@2152:         self.BackupAllSDOData = self.SaveAllSDOData
Edouard@2152:     
Edouard@2152:     def ClearSDODataSet(self):
Edouard@2152:         """
Edouard@2152:         Clear the specified SDO entry information.
Edouard@2152:         """ 
Edouard@2152:         for count in range(6):
Edouard@2152:             self.SaveSDOData.append([])
Edouard@2152:     
Edouard@2152:     #-------------------------------------------------------------------------------
Edouard@2152:     #                        Used PDO Monitoring
Edouard@2152:     #-------------------------------------------------------------------------------
Edouard@2152:     def RequestPDOInfo(self):
Edouard@2152:         """
Edouard@2152:         Load slave information from RootClass (XML data) and parse the information (calling SlavePDOData() method).
Edouard@2152:         """ 
Edouard@2152:         # Load slave information from ESI XML file (def EthercatMaster.py)
Edouard@2152:         slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos())
Edouard@2152:         
Edouard@2152:         type_infos = slave.getType()
Edouard@2152:         device, alignment = self.Controler.CTNParent.GetModuleInfos(type_infos)
Edouard@2152:         # Initialize PDO data set
Edouard@2152:         self.ClearDataSet()
Edouard@2152:         
Edouard@2152:         # if 'device' object is valid, call SavePDOData() to parse PDO data 
Edouard@2152:         if device is not None :
Edouard@2152:             self.SavePDOData(device)
Edouard@2152:     
Edouard@2152:     def SavePDOData(self, device):
Edouard@2152:         """
Edouard@2152:         Parse PDO data and store the results in TXPDOCategory and RXPDOCategory
Edouard@2152:         Tx(Rx)PDOCategory : index, name, entry number
Edouard@2152:         Tx(Rx)Info : entry index, sub index, name, length, type
Edouard@2152:         @param device : Slave information extracted from ESI XML file
Edouard@2152:         """ 
Edouard@2152:         # Parsing TXPDO entries
Edouard@2152:         for pdo, pdo_info in ([(pdo, "Inputs") for pdo in device.getTxPdo()]):
Edouard@2152:             # Save pdo_index, entry, and name of each entry
Edouard@2152:             pdo_index = ExtractHexDecValue(pdo.getIndex().getcontent())
Edouard@2152:             entries = pdo.getEntry()
Edouard@2152:             pdo_name = ExtractName(pdo.getName())
Edouard@2152:             
Edouard@2152:             # Initialize entry number count
Edouard@2152:             count = 0
Edouard@2152:             
Edouard@2152:             # Parse entries
Edouard@2152:             for entry in entries:
Edouard@2152:                 # Save index and subindex
Edouard@2152:                 index = ExtractHexDecValue(entry.getIndex().getcontent())
Edouard@2152:                 subindex = ExtractHexDecValue(entry.getSubIndex())
Edouard@2152:                 # if entry name exists, save entry data
Edouard@2152:                 if ExtractName(entry.getName()) is not None :
Edouard@2152:                     entry_infos = {
Edouard@2152:                                 "entry_index" : index,
Edouard@2152:                                 "subindex" : subindex,
Edouard@2152:                                 "name" : ExtractName(entry.getName()),
Edouard@2152:                                 "bitlen" : entry.getBitLen(),
Edouard@2152:                                 "type" : entry.getDataType().getcontent()
Edouard@2152:                                     }
Edouard@2152:                     self.TxPDOInfo.append(entry_infos)
Edouard@2152:                     count += 1
Edouard@2152:               
Edouard@2152:             categorys = {"pdo_index" : pdo_index, "name" : pdo_name, "number_of_entry" : count}  
Edouard@2152:             self.TxPDOCategory.append(categorys)
Edouard@2152: 
Edouard@2152:         # Parsing RxPDO entries
Edouard@2152:         for pdo, pdo_info in ([(pdo, "Outputs") for pdo in device.getRxPdo()]):
Edouard@2152:             # Save pdo_index, entry, and name of each entry
Edouard@2152:             pdo_index = ExtractHexDecValue(pdo.getIndex().getcontent())
Edouard@2152:             entries = pdo.getEntry()
Edouard@2152:             pdo_name = ExtractName(pdo.getName())
Edouard@2152:             
Edouard@2152:             # Initialize entry number count
Edouard@2152:             count = 0          
Edouard@2152: 
Edouard@2152:             # Parse entries          
Edouard@2152:             for entry in entries:
Edouard@2152:                 # Save index and subindex
Edouard@2152:                 index = ExtractHexDecValue(entry.getIndex().getcontent())
Edouard@2152:                 subindex = ExtractHexDecValue(entry.getSubIndex())
Edouard@2152:                 # if entry name exists, save entry data
Edouard@2152:                 if ExtractName(entry.getName()) is not None :
Edouard@2152:                     entry_infos = {
Edouard@2152:                                 "entry_index" : index,
Edouard@2152:                                 "subindex" : subindex,
Edouard@2152:                                 "name" : ExtractName(entry.getName()),
Edouard@2152:                                 "bitlen" : str(entry.getBitLen()),
Edouard@2152:                                 "type" : entry.getDataType().getcontent()
Edouard@2152:                                     }
Edouard@2152:                     self.RxPDOInfo.append(entry_infos)
Edouard@2152:                     count += 1
Edouard@2152:     
Edouard@2152:             categorys = {"pdo_index" : pdo_index, "name" : pdo_name, "number_of_entry" : count}  
Edouard@2152:             self.RxPDOCategory.append(categorys) 
Edouard@2152: 
Edouard@2152:     def GetTxPDOCategory(self):
Edouard@2152:         """
Edouard@2152:         Get TxPDOCategory data structure (Meta informaton of TxPDO).
Edouard@2152:         TxPDOCategorys : index, name, number of entries
Edouard@2152:         @return TxPDOCategorys
Edouard@2152:         """ 
Edouard@2152:         return self.TxPDOCategory
Edouard@2152:         
Edouard@2152:     def GetRxPDOCategory(self):
Edouard@2152:         """
Edouard@2152:         Get RxPDOCategory data structure (Meta information of RxPDO).
Edouard@2152:         RxPDOCategorys : index, name, number of entries
Edouard@2152:         @return RxPDOCategorys
Edouard@2152:         """ 
Edouard@2152:         return self.RxPDOCategory
Edouard@2152:         
Edouard@2152:     def GetTxPDOInfo(self):
Edouard@2152:         """
Edouard@2152:         Get TxPDOInfo data structure (Detailed information on TxPDO entries). 
Edouard@2152:         TxPDOInfos : entry index, sub index, name, length, type
Edouard@2152:         @return TxPDOInfos
Edouard@2152:         """ 
Edouard@2152:         return self.TxPDOInfo
Edouard@2152:         
Edouard@2152:     def GetRxPDOInfo(self):
Edouard@2152:         """
Edouard@2152:         Get RxPDOInfo data structure (Detailed information on RxPDO entries). 
Edouard@2152:         RxPDOInfos : entry index, sub index, name, length, type
Edouard@2152:         @return RxPDOInfos
Edouard@2152:         """ 
Edouard@2152:         return self.RxPDOInfo
Edouard@2152:         
Edouard@2152:     def ClearDataSet(self):
Edouard@2152:         """
Edouard@2152:         Initialize PDO management data structure.
Edouard@2152:         """ 
Edouard@2152:         self.TxPDOInfos = []
Edouard@2152:         self.TxPDOCategorys = []
Edouard@2152:         self.RxPDOInfos = []
Edouard@2152:         self.RxPDOCategorys = []
Edouard@2152:                
Edouard@2152:     #-------------------------------------------------------------------------------
Edouard@2152:     #                        Used EEPROM Management
Edouard@2152:     #-------------------------------------------------------------------------------
Edouard@2152:     # Base data types in ETG2000; format = {"Name": "BitSize"}
Edouard@2152:     BaseDataTypeDict = {"BOOL": "01",
Edouard@2152:                         "SINT": "02",
Edouard@2152:                         "INT": "03",
Edouard@2152:                         "DINT": "04",
Edouard@2152:                         "USINT": "05",
Edouard@2152:                         "UINT": "06",
Edouard@2152:                         "UDINT": "07",
Edouard@2152:                         "REAL": "08",
Edouard@2152:                         "INT24": "10",
Edouard@2152:                         "LREAL": "11",
Edouard@2152:                         "INT40": "12",
Edouard@2152:                         "INT48": "13",
Edouard@2152:                         "INT56": "14",
Edouard@2152:                         "LINT": "15",
Edouard@2152:                         "UINT24": "16",
Edouard@2152:                         "UINT40": "18",
Edouard@2152:                         "UINT48": "19",
Edouard@2152:                         "UINT56": "1a",
Edouard@2152:                         "ULINT": "1b",
Edouard@2152:                         "USINT": "1e",
Edouard@2152:                         "BITARR8": "2d",
Edouard@2152:                         "BITARR16": "2e",
Edouard@2152:                         "BITARR32": "2f",
Edouard@2152:                         "BIT1": "30",
Edouard@2152:                         "BIT2": "31",
Edouard@2152:                         "BIT3": "32",
Edouard@2152:                         "BIT4": "33",
Edouard@2152:                         "BIT5": "34",
Edouard@2152:                         "BIT6": "35",
Edouard@2152:                         "BIT7": "36",
Edouard@2152:                         "BIT8": "37"}        
Edouard@2152:         
Edouard@2152:     def GetSmartViewInfos(self):
Edouard@2152:         """
Edouard@2152:         Parse XML data for "Smart View" of EEPROM contents.
Edouard@2152:         @return smartview_infos : EEPROM contents dictionary
Edouard@2152:         """ 
Edouard@2152: 
Edouard@2152:         smartview_infos = {"eeprom_size": 128,
Edouard@2152:                            "pdi_type": 0,
Edouard@2152:                            "device_emulation": "False",
Edouard@2152:                            "vendor_id": '0x00000000',
Edouard@2152:                            "product_code": '0x00000000',
Edouard@2152:                            "revision_no": '0x00000000',
Edouard@2152:                            "serial_no": '0x00000000',
Edouard@2152:                            "supported_mailbox": "",
Edouard@2152:                            "mailbox_bootstrapconf_outstart": '0',
Edouard@2152:                            "mailbox_bootstrapconf_outlength": '0',
Edouard@2152:                            "mailbox_bootstrapconf_instart": '0',
Edouard@2152:                            "mailbox_bootstrapconf_inlength": '0',
Edouard@2152:                            "mailbox_standardconf_outstart": '0',
Edouard@2152:                            "mailbox_standardconf_outlength": '0',
Edouard@2152:                            "mailbox_standardconf_instart": '0',
Edouard@2152:                            "mailbox_standardconf_inlength": '0'}
Edouard@2152:         
Edouard@2152:         slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos())
Edouard@2152:         type_infos = slave.getType()
Edouard@2152:         device, alignment = self.Controler.CTNParent.GetModuleInfos(type_infos)
Edouard@2152: 
Edouard@2152:         # 'device' represents current slave device selected by user
Edouard@2152:         if device is not None:
Edouard@2163:             for eeprom_element in device.getEeprom().getcontent():
Edouard@2152:                 # get EEPROM size; <Device>-<Eeprom>-<ByteSize>
Edouard@2152:                 if eeprom_element["name"] == "ByteSize":
Edouard@2163:                     smartview_infos["eeprom_size"] = eeprom_element
Edouard@2152:                         
Edouard@2152:                 elif eeprom_element["name"] == "ConfigData":
Edouard@2163:                     configData_data = self.DecimalToHex(eeprom_element)
Edouard@2152:                     # get PDI type; <Device>-<Eeprom>-<ConfigData> address 0x00
Edouard@2152:                     smartview_infos["pdi_type"] = int(configData_data[0:2], 16)
Edouard@2152:                     # get state of device emulation; <Device>-<Eeprom>-<ConfigData> address 0x01
Edouard@2152:                     if "{:0>8b}".format(int(configData_data[2:4], 16))[7] == '1':
Edouard@2152:                         smartview_infos["device_emulation"] = "True"
Edouard@2152: 
Edouard@2152:                 elif eeprom_element["name"] == "BootStrap":
Edouard@2163:                     bootstrap_data = "{:0>16x}".format(eeprom_element)
Edouard@2152:                     # get bootstrap configuration; <Device>-<Eeprom>-<BootStrap>
Edouard@2152:                     for cfg, iter in [("mailbox_bootstrapconf_outstart", 0), 
Edouard@2152:                                       ("mailbox_bootstrapconf_outlength", 1),
Edouard@2152:                                       ("mailbox_bootstrapconf_instart", 2),
Edouard@2152:                                       ("mailbox_bootstrapconf_inlength", 3)]:
Edouard@2152:                         smartview_infos[cfg] = str(int(bootstrap_data[4*iter+2:4*(iter+1)]+bootstrap_data[4*iter:4*iter+2], 16))
Edouard@2152:             
Edouard@2152:             # get protocol (profile) types supported by mailbox; <Device>-<Mailbox>
Edouard@2163:             mb = device.getMailbox()
Edouard@2163:             if mb is not None:
Edouard@2163:                 for mailbox_protocol in mailbox_protocols:
Edouard@2163:                     if getattr(mb,"get%s"%mailbox_protocol)() is not None:
Edouard@2163:                         smartview_infos["supported_mailbox"] += "%s,  "%mailbox_protocol
Edouard@2152:             smartview_infos["supported_mailbox"] = smartview_infos["supported_mailbox"].strip(",  ")
Edouard@2152:                 
Edouard@2152:             # get standard configuration of mailbox; <Device>-<Sm>
Edouard@2152:             for sm_element in device.getSm():
Edouard@2152:                 if sm_element.getcontent() == "MBoxOut":
Edouard@2152:                     smartview_infos["mailbox_standardconf_outstart"] = str(ExtractHexDecValue(sm_element.getStartAddress()))
Edouard@2152:                     smartview_infos["mailbox_standardconf_outlength"] = str(ExtractHexDecValue(sm_element.getDefaultSize()))
Edouard@2152:                 elif sm_element.getcontent() == "MBoxIn":
Edouard@2152:                     smartview_infos["mailbox_standardconf_instart"] = str(ExtractHexDecValue(sm_element.getStartAddress()))
Edouard@2152:                     smartview_infos["mailbox_standardconf_inlength"] = str(ExtractHexDecValue(sm_element.getDefaultSize()))
Edouard@2152:                 else:
Edouard@2152:                     pass
Edouard@2152: 
Edouard@2152:             # get device identity from <Device>-<Type>
Edouard@2152:             #  vendor ID; by default, pre-defined value in self.ModulesLibrary
Edouard@2152:             #             if device type in 'vendor' item equals to actual slave device type, set 'vendor_id' to vendor ID.
Edouard@2152:             for vendor_id, vendor in self.Controler.CTNParent.CTNParent.ModulesLibrary.Library.iteritems():
Edouard@2152:                 for available_device in vendor["groups"][vendor["groups"].keys()[0]]["devices"]:
Edouard@2152:                     if available_device[0] == type_infos["device_type"]:
Edouard@2152:                         smartview_infos["vendor_id"] = "0x" + "{:0>8x}".format(vendor_id)
Edouard@2152:                         
Edouard@2152:             #  product code; 
Edouard@2152:             if device.getType().getProductCode() is not None:
Edouard@2152:                 product_code = device.getType().getProductCode()
Edouard@2152:                 smartview_infos["product_code"] = "0x"+"{:0>8x}".format(ExtractHexDecValue(product_code))
Edouard@2152:                 
Edouard@2152:             #  revision number; 
Edouard@2152:             if device.getType().getRevisionNo() is not None:
Edouard@2152:                 revision_no = device.getType().getRevisionNo()
Edouard@2152:                 smartview_infos["revision_no"] = "0x"+"{:0>8x}".format(ExtractHexDecValue(revision_no))
Edouard@2152:                 
Edouard@2152:             #  serial number;
Edouard@2152:             if device.getType().getSerialNo() is not None:
Edouard@2152:                 serial_no = device.getType().getSerialNo()
Edouard@2152:                 smartview_infos["serial_no"] = "0x"+"{:0>8x}".format(ExtractHexDecValue(serial_no))
Edouard@2152:                                             
Edouard@2152:             return smartview_infos
Edouard@2152:         
Edouard@2152:         else:
Edouard@2152:             return None
Edouard@2152:         
Edouard@2152:     def DecimalToHex(self, decnum):
Edouard@2152:         """
Edouard@2152:         Convert decimal value into hexadecimal representation. 
Edouard@2152:         @param decnum : decimal value
Edouard@2152:         @return hex_data : hexadecimal representation of input value in decimal
Edouard@2152:         """ 
Edouard@2152:         value = "%x" % decnum
Edouard@2152:         value_len = len(value)
Edouard@2152:         if (value_len % 2) == 0:
Edouard@2152:             hex_len = value_len
Edouard@2152:         else:
Edouard@2152:             hex_len = (value_len / 2) * 2 + 2
Edouard@2152:         
Edouard@2152:         hex_data = ("{:0>"+str(hex_len)+"x}").format(decnum)
Edouard@2152:         
Edouard@2152:         return hex_data
Edouard@2152: 
Edouard@2152:     def SiiRead(self):
Edouard@2152:         """
Edouard@2152:         Get slave EEPROM contents maintained by master device using "ethercat sii_read -p %d" command.
Edouard@2152:         Command example : "ethercat sii_read -p 0"
Edouard@2152:         @return return_val : result of "ethercat sii_read" (binary data)
Edouard@2152:         """ 
Edouard@2152:         error, return_val = self.Controler.RemoteExec(SII_READ%(self.Controler.GetSlavePos()), return_val = None)
Edouard@2152:         self.SiiData = return_val
Edouard@2152:         return return_val
Edouard@2152: 
Edouard@2152:     def SiiWrite(self, binary):
Edouard@2152:         """
Edouard@2152:         Overwrite slave EEPROM contents using "ethercat sii_write -p %d" command.
Edouard@2152:         Command example : "ethercat sii_write -p 0 - (binary contents)"
Edouard@2152:         @param binary : EEPROM contents in binary data format
Edouard@2152:         @return return_val : result of "ethercat sii_write" (If it succeeds, the return value is NULL.)
Edouard@2152:         """ 
Edouard@2152:         error, return_val = self.Controler.RemoteExec(SII_WRITE%(self.Controler.GetSlavePos()), return_val = None, sii_data = binary)
Edouard@2152:         return return_val 
Edouard@2152: 
Edouard@2152:     def LoadData(self):
Edouard@2152:         """
Edouard@2152:         Loading data from EEPROM use Sii_Read Method
Edouard@2152:         @return self.BinaryCode : slave EEPROM data in binary format (zero-padded)
Edouard@2152:         """ 
Edouard@2152:         return_val = self.Controler.CommonMethod.SiiRead()
Edouard@2152:         self.BinaryCode = return_val
Edouard@2152:         self.Controler.SiiData = self.BinaryCode
Edouard@2152: 
Edouard@2152:         # append zero-filled padding data up to EEPROM size
Edouard@2152:         for index in range(self.SmartViewInfosFromXML["eeprom_size"] - len(self.BinaryCode)):
Edouard@2152:             self.BinaryCode = self.BinaryCode +'ff'.decode('hex')
Edouard@2152:               
Edouard@2152:         return self.BinaryCode
Edouard@2152: 
Edouard@2152:     def HexRead(self, binary):
Edouard@2152:         """
Edouard@2152:         Convert binary digit representation into hexadecimal representation for "Hex View" menu.
Edouard@2152:         @param binary : binary digits
Edouard@2152:         @return hexCode : hexadecimal digits
Edouard@2152:         @return hexview_table_row, hexview_table_col : Grid size for "Hex View" UI
Edouard@2152:         """ 
Edouard@2152:         row_code = []
Edouard@2152:         row_text = ""
Edouard@2152:         row = 0
Edouard@2152:         hex_code = []
Edouard@2152: 
Edouard@2152:         hexview_table_col = 17
Edouard@2152:         
Edouard@2152:         for index in range(0, len(binary)) :
Edouard@2152:             if len(binary[index]) != 1:
Edouard@2152:                 break
Edouard@2152:             else:
Edouard@2152:                 digithexstr = hex(ord(binary[index])) 
Edouard@2152: 
Edouard@2152:                 tempvar2 = digithexstr[2:4]
Edouard@2152:                 if len(tempvar2) == 1:
Edouard@2152:                     tempvar2 = "0" + tempvar2
Edouard@2152:                 row_code.append(tempvar2) 
Edouard@2152:                 
Edouard@2152:                 if int(digithexstr, 16)>=32 and int(digithexstr, 16)<=126:
Edouard@2152:                     row_text = row_text + chr(int(digithexstr, 16))
Edouard@2152:                 else:
Edouard@2152:                     row_text = row_text + "."
Edouard@2152:                 
Edouard@2152:                 if index != 0 : 
Edouard@2152:                     if len(row_code) == (hexview_table_col - 1):
Edouard@2152:                         row_code.append(row_text)
Edouard@2152:                         hex_code.append(row_code)
Edouard@2152:                         row_text = ""
Edouard@2152:                         row_code = []
Edouard@2152:                         row = row + 1        
Edouard@2152:                                         
Edouard@2152:         hexview_table_row = row
Edouard@2152:         
Edouard@2152:         return hex_code, hexview_table_row, hexview_table_col
Edouard@2152:     
Edouard@2152:     def GenerateEEPROMList(self, data, direction, length):
Edouard@2152:         """
Edouard@2152:         Generate EEPROM data list by reconstructing 'data' string.
Edouard@2152:         example : data="12345678", direction=0, length=8 -> eeprom_list=['12', '34', '56', '78']
Edouard@2152:                   data="12345678", direction=1, length=8 -> eeprom_list=['78', '56', '34', '12']
Edouard@2152:         @param data : string to be reconstructed
Edouard@2152:         @param direction : endianness
Edouard@2152:         @param length : data length
Edouard@2152:         @return eeprom_list : reconstructed list data structure
Edouard@2152:         """ 
Edouard@2152:         eeprom_list = []
Edouard@2152: 
Edouard@2152:         if direction is 0 or 1:
Edouard@2152:             for i in range(length/2):
Edouard@2152:                 if data == "":
Edouard@2152:                     eeprom_list.append("00")
Edouard@2152:                 else:
Edouard@2152:                     eeprom_list.append(data[direction*(length-2):direction*(length-2)+2])
Edouard@2152:                 data = data[(1-direction)*2:length-direction*2]
Edouard@2152:                 length -= 2
Edouard@2152:         return eeprom_list
Edouard@2152:     
Edouard@2152:     def XmlToEeprom(self):
Edouard@2152:         """
Edouard@2152:         Extract slave EEPROM contents using slave ESI XML file.
Edouard@2152:           - Mandatory parts
Edouard@2152:           - String category : ExtractEEPROMStringCategory()
Edouard@2152:           - General category : ExtractEEPROMGeneralCategory()
Edouard@2152:           - FMMU category : ExtractEEPROMFMMUCategory
Edouard@2152:           - SyncM category : ExtractEEPROMSyncMCategory()
Edouard@2152:           - Tx/RxPDO category : ExtractEEPROMPDOCategory()
Edouard@2152:           - DC category : ExtractEEPROMDCCategory()
Edouard@2152:         @return eeprom_binary 
Edouard@2152:         """ 
Edouard@2152:         eeprom = []
Edouard@2152:         data = ""
Edouard@2152:         eeprom_size = 0
Edouard@2152:         eeprom_binary = ""
Edouard@2152: 
Edouard@2152:         # 'device' is the slave device of the current EtherCAT slave plugin
Edouard@2152:         slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos())
Edouard@2152:         type_infos = slave.getType()
Edouard@2152:         device, alignment = self.Controler.CTNParent.GetModuleInfos(type_infos)
Edouard@2152:         
Edouard@2152:         if device is not None:
Edouard@2152:             # get ConfigData for EEPROM offset 0x0000-0x000d; <Device>-<Eeprom>-<ConfigData>
Edouard@2163:             for eeprom_element in device.getEeprom().getcontent():
Edouard@2152:                 if eeprom_element["name"] == "ConfigData":
Edouard@2163:                     data = self.DecimalToHex(eeprom_element)
Edouard@2152:             eeprom += self.GenerateEEPROMList(data, 0, 28)
Edouard@2152:             
Edouard@2152:             # calculate CRC for EEPROM offset 0x000e-0x000f
Edouard@2152:             crc = 0x48
Edouard@2152:             for segment in eeprom:
Edouard@2152:                 for i in range(8):
Edouard@2152:                     bit = crc & 0x80
Edouard@2152:                     crc = (crc << 1) | ((int(segment, 16) >> (7 - i)) & 0x01)
Edouard@2152:                     if bit:
Edouard@2152:                         crc ^= 0x07   
Edouard@2152:             for k in range(8):
Edouard@2152:                 bit = crc & 0x80
Edouard@2152:                 crc <<= 1
Edouard@2152:                 if bit:
Edouard@2152:                     crc ^= 0x07      
Edouard@2152:             eeprom.append(hex(crc)[len(hex(crc))-3:len(hex(crc))-1])
Edouard@2152:             eeprom.append("00")
Edouard@2152:             
Edouard@2152:             # get VendorID for EEPROM offset 0x0010-0x0013;
Edouard@2152:             data = ""
Edouard@2152:             for vendor_id, vendor in self.Controler.CTNParent.CTNParent.ModulesLibrary.Library.iteritems():
Edouard@2152:                 for available_device in vendor["groups"][vendor["groups"].keys()[0]]["devices"]:
Edouard@2152:                     if available_device[0] == type_infos["device_type"]:
Edouard@2152:                         data = "{:0>8x}".format(vendor_id)
Edouard@2152:             eeprom += self.GenerateEEPROMList(data, 1, 8)
Edouard@2152:             
Edouard@2152:             # get Product Code for EEPROM offset 0x0014-0x0017;
Edouard@2152:             data = ""
Edouard@2152:             if device.getType().getProductCode() is not None:
Edouard@2152:                 data = "{:0>8x}".format(ExtractHexDecValue(device.getType().getProductCode()))
Edouard@2152:             eeprom += self.GenerateEEPROMList(data, 1, 8)
Edouard@2152:             
Edouard@2152:             # get Revision Number for EEPROM offset 0x0018-0x001b;
Edouard@2152:             data = ""
Edouard@2152:             if device.getType().getRevisionNo() is not None:
Edouard@2152:                 data = "{:0>8x}".format(ExtractHexDecValue(device.getType().getRevisionNo()))
Edouard@2152:             eeprom += self.GenerateEEPROMList(data, 1, 8)  
Edouard@2152:             
Edouard@2152:             # get Serial Number for EEPROM 0x001c-0x001f;
Edouard@2152:             data = ""
Edouard@2152:             if device.getType().getSerialNo() is not None:
Edouard@2152:                 data = "{:0>8x}".format(ExtractHexDecValue(device.getType().getSerialNo()))
Edouard@2152:             eeprom += self.GenerateEEPROMList(data, 1, 8)
Edouard@2152:                 
Edouard@2152:             # get Execution Delay for EEPROM 0x0020-0x0021; not analyzed yet
Edouard@2152:             eeprom.append("00")
Edouard@2152:             eeprom.append("00")
Edouard@2152:             
Edouard@2152:             # get Port0/1 Delay for EEPROM offset 0x0022-0x0025; not analyzed yet
Edouard@2152:             eeprom.append("00")
Edouard@2152:             eeprom.append("00")
Edouard@2152:             eeprom.append("00")
Edouard@2152:             eeprom.append("00")
Edouard@2152:             
Edouard@2152:             # reserved for EEPROM offset 0x0026-0x0027;
Edouard@2152:             eeprom.append("00")
Edouard@2152:             eeprom.append("00")
Edouard@2152: 
Edouard@2152:             # get BootStrap for EEPROM offset 0x0028-0x002e; <Device>-<Eeprom>-<BootStrap>
Edouard@2152:             data = ""
Edouard@2163:             for eeprom_element in device.getEeprom().getcontent():
Edouard@2152:                 if eeprom_element["name"] == "BootStrap":
Edouard@2163:                     data = "{:0>16x}".format(eeprom_element)
Edouard@2152:             eeprom += self.GenerateEEPROMList(data, 0, 16)
Edouard@2152:             
Edouard@2152:             # get Standard Mailbox for EEPROM offset 0x0030-0x0037; <Device>-<sm>
Edouard@2152:             data = ""
Edouard@2163:             standard_send_mailbox_offset = None
Edouard@2163:             standard_send_mailbox_size = None
Edouard@2163:             standard_receive_mailbox_offset = None
Edouard@2163:             standard_receive_mailbox_size = None
Edouard@2152:             for sm_element in device.getSm():
Edouard@2152:                 if sm_element.getcontent() == "MBoxOut":
Edouard@2152:                     standard_receive_mailbox_offset = "{:0>4x}".format(ExtractHexDecValue(sm_element.getStartAddress()))
Edouard@2152:                     standard_receive_mailbox_size = "{:0>4x}".format(ExtractHexDecValue(sm_element.getDefaultSize()))
Edouard@2152:                 elif sm_element.getcontent() == "MBoxIn":
Edouard@2152:                     standard_send_mailbox_offset = "{:0>4x}".format(ExtractHexDecValue(sm_element.getStartAddress()))
Edouard@2152:                     standard_send_mailbox_size = "{:0>4x}".format(ExtractHexDecValue(sm_element.getDefaultSize()))
Edouard@2152:                     
Edouard@2152:             if standard_receive_mailbox_offset is None:
Edouard@2152:                 eeprom.append("00")
Edouard@2152:                 eeprom.append("00")
Edouard@2152:             else:
Edouard@2152:                 eeprom.append(standard_receive_mailbox_offset[2:4])
Edouard@2152:                 eeprom.append(standard_receive_mailbox_offset[0:2])
Edouard@2152:             if standard_receive_mailbox_size is None:
Edouard@2152:                 eeprom.append("00")
Edouard@2152:                 eeprom.append("00")
Edouard@2152:             else:
Edouard@2152:                 eeprom.append(standard_receive_mailbox_size[2:4])
Edouard@2152:                 eeprom.append(standard_receive_mailbox_size[0:2])
Edouard@2152:             if standard_send_mailbox_offset is None:
Edouard@2152:                 eeprom.append("00")
Edouard@2152:                 eeprom.append("00")
Edouard@2152:             else:
Edouard@2152:                 eeprom.append(standard_send_mailbox_offset[2:4])
Edouard@2152:                 eeprom.append(standard_send_mailbox_offset[0:2])
Edouard@2152:             if standard_send_mailbox_size is None:
Edouard@2152:                 eeprom.append("00")
Edouard@2152:                 eeprom.append("00")
Edouard@2152:             else:
Edouard@2152:                 eeprom.append(standard_send_mailbox_size[2:4])
Edouard@2152:                 eeprom.append(standard_send_mailbox_size[0:2])
Edouard@2152:             
Edouard@2152:             # get supported mailbox protocols for EEPROM offset 0x0038-0x0039;
Edouard@2152:             data = 0
Edouard@2163:             mb = device.getMailbox()
Edouard@2163:             if mb is not None :
Edouard@2163:                 for bit,mbprot in enumerate(mailbox_protocols):
Edouard@2163:                     if getattr(mb,"get%s"%mbprot)() is not None:
Edouard@2163:                         data += 1<<bit
Edouard@2152:             data = "{:0>4x}".format(data)
Edouard@2152:             eeprom.append(data[2:4])
Edouard@2152:             eeprom.append(data[0:2])
Edouard@2152:             
Edouard@2152:             # resereved for EEPROM offset 0x003a-0x007b;
Edouard@2152:             for i in range(0x007b-0x003a+0x0001):
Edouard@2152:                 eeprom.append("00")
Edouard@2152:             
Edouard@2152:             # get EEPROM size for EEPROM offset 0x007c-0x007d;
Edouard@2152:             data = ""
Edouard@2163:             for eeprom_element in device.getEeprom().getcontent():
Edouard@2152:                 if eeprom_element["name"] == "ByteSize":
Edouard@2163:                     eeprom_size = int(str(eeprom_element))
Edouard@2163:                     data = "{:0>4x}".format(int(eeprom_element)/1024*8-1)
Edouard@2152: 
Edouard@2152:             if data == "":
Edouard@2152:                 eeprom.append("00")
Edouard@2152:                 eeprom.append("00")
Edouard@2152:             else:
Edouard@2152:                 eeprom.append(data[2:4])
Edouard@2152:                 eeprom.append(data[0:2])
Edouard@2152:                 
Edouard@2152:             # Version for EEPROM 0x007e-0x007f; 
Edouard@2152:             #  According to "EtherCAT Slave Device Description(V0.3.0)"
Edouard@2152:             eeprom.append("01")
Edouard@2152:             eeprom.append("00")
Edouard@2152:             
Edouard@2152:             # append String Category data
Edouard@2152:             for data in self.ExtractEEPROMStringCategory(device):
Edouard@2152:                 eeprom.append(data)
Edouard@2152:                 
Edouard@2152:             # append General Category data
Edouard@2152:             for data in self.ExtractEEPROMGeneralCategory(device):
Edouard@2152:                 eeprom.append(data)
Edouard@2152:                 
Edouard@2152:             # append FMMU Category data
Edouard@2152:             for data in self.ExtractEEPROMFMMUCategory(device):
Edouard@2152:                 eeprom.append(data)
Edouard@2152:             
Edouard@2152:             # append SyncM Category data
Edouard@2152:             for data in self.ExtractEEPROMSyncMCategory(device):
Edouard@2152:                 eeprom.append(data)
Edouard@2152:                 
Edouard@2152:             # append TxPDO Category data
Edouard@2152:             for data in self.ExtractEEPROMPDOCategory(device, "TxPdo"):
Edouard@2152:                 eeprom.append(data)
Edouard@2152:                 
Edouard@2152:             # append RxPDO Category data
Edouard@2152:             for data in self.ExtractEEPROMPDOCategory(device, "RxPdo"):
Edouard@2152:                 eeprom.append(data)
Edouard@2152:                 
Edouard@2152:             # append DC Category data
Edouard@2152:             for data in self.ExtractEEPROMDCCategory(device):
Edouard@2152:                 eeprom.append(data)
Edouard@2152:             
Edouard@2152:             # append padding
Edouard@2152:             padding = eeprom_size-len(eeprom)
Edouard@2152:             for i in range(padding):
Edouard@2152:                 eeprom.append("ff")
Edouard@2152:             
Edouard@2152:             # convert binary code
Edouard@2152:             for index in range(eeprom_size):
Edouard@2152:                 eeprom_binary = eeprom_binary + eeprom[index].decode('hex')
Edouard@2152:             
Edouard@2152:             return eeprom_binary
Edouard@2152:     
Edouard@2152:     def ExtractEEPROMStringCategory(self, device):
Edouard@2152:         """
Edouard@2152:         Extract "Strings" category data from slave ESI XML and generate EEPROM image data.
Edouard@2152:         @param device : 'device' object in the slave ESI XML
Edouard@2152:         @return eeprom : "Strings" category EEPROM image data
Edouard@2152:         """ 
Edouard@2152:         eeprom = []
Edouard@2152:         self.Strings = []
Edouard@2152:         data = "" 
Edouard@2152:         count = 0 # string counter
Edouard@2152:         padflag = False # padding flag if category length is odd
Edouard@2152:         
Edouard@2152:         # index information for General Category in EEPROM
Edouard@2152:         self.GroupIdx = 0
Edouard@2152:         self.ImgIdx = 0
Edouard@2152:         self.OrderIdx = 0
Edouard@2152:         self.NameIdx = 0
Edouard@2152:         
Edouard@2152:         # flag for preventing duplicated vendor specific data 
Edouard@2152:         typeflag = False
Edouard@2152:         grouptypeflag = False
Edouard@2152:         groupnameflag = False
Edouard@2152:         devnameflag = False
Edouard@2152:         imageflag = False
Edouard@2152:         
Edouard@2152:         # vendor specific data
Edouard@2152:         #   element1; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Type>
Edouard@2152:         #   vendor_specific_data : vendor specific data (binary type)
Edouard@2152:         vendor_specific_data = ""
Edouard@2152:         #   vendor_spec_strings : list of vendor specific "strings" for preventing duplicated strings
Edouard@2152:         vendor_spec_strings = []
Edouard@2152:         for element in device.getType().getcontent():
Edouard@2152:             data += element
Edouard@2152:         if data is not "" and type(data) == unicode:
Edouard@2152:             for vendor_spec_string in vendor_spec_strings: 
Edouard@2152:                 if data == vendor_spec_string:
Edouard@2152:                     self.OrderIdx = vendor_spec_strings.index(data)+1
Edouard@2152:                     typeflag = True
Edouard@2152:                     break
Edouard@2152:             if typeflag is False:
Edouard@2152:                 count += 1
Edouard@2152:                 self.Strings.append(data)
Edouard@2152:                 vendor_spec_strings.append(data)
Edouard@2152:                 typeflag = True
Edouard@2152:                 self.OrderIdx = count
Edouard@2152:                 vendor_specific_data += "{:0>2x}".format(len(data))
Edouard@2152:                 for character in range(len(data)):
Edouard@2152:                     vendor_specific_data += "{:0>2x}".format(ord(data[character]))
Edouard@2152:         data = ""
Edouard@2152:         
Edouard@2152:         #  element2-1; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<GroupType>
Edouard@2152:         data = device.getGroupType()
Edouard@2152:         if data is not None and type(data) == unicode:
Edouard@2152:             for vendor_spec_string in vendor_spec_strings:
Edouard@2152:                 if data == vendor_spec_string:
Edouard@2152:                     self.GroupIdx = vendor_spec_strings.index(data)+1
Edouard@2152:                     grouptypeflag = True
Edouard@2152:                     break
Edouard@2152:             if grouptypeflag is False:
Edouard@2152:                 grouptype = data
Edouard@2152:                 count += 1
Edouard@2152:                 self.Strings.append(data)
Edouard@2152:                 vendor_spec_strings.append(data)
Edouard@2152:                 grouptypeflag = True
Edouard@2152:                 self.GroupIdx = count
Edouard@2152:                 vendor_specific_data += "{:0>2x}".format(len(data))
Edouard@2152:                 for character in range(len(data)):
Edouard@2152:                     vendor_specific_data += "{:0>2x}".format(ord(data[character]))
Edouard@2152:         
Edouard@2152:         #  element2-2; <EtherCATInfo>-<Groups>-<Group>-<Type>            
Edouard@2152:         if grouptypeflag is False: 
Edouard@2152:             if self.Controler.CTNParent.CTNParent.ModulesLibrary.Library is not None:
Edouard@2152:                 for vendor_id, vendor in self.Controler.CTNParent.CTNParent.ModulesLibrary.Library.iteritems():
Edouard@2152:                     for group_type, group_etc in vendor["groups"].iteritems():
Edouard@2152:                         for device_item in group_etc["devices"]:
Edouard@2152:                             if device == device_item[1]: 
Edouard@2152:                                 data = group_type
Edouard@2152:                 if data is not None and type(data) == unicode:
Edouard@2152:                     for vendor_spec_string in vendor_spec_strings:
Edouard@2152:                         if data == vendor_spec_string:
Edouard@2152:                             self.GroupIdx = vendor_spec_strings.index(data)+1
Edouard@2152:                             grouptypeflag = True
Edouard@2152:                             break
Edouard@2152:                     if grouptypeflag is False:
Edouard@2152:                         grouptype = data
Edouard@2152:                         count += 1
Edouard@2152:                         self.Strings.append(data)
Edouard@2152:                         vendor_spec_strings.append(data)
Edouard@2152:                         grouptypeflag = True
Edouard@2152:                         self.GroupIdx = count
Edouard@2152:                         vendor_specific_data += "{:0>2x}".format(len(data))
Edouard@2152:                         for character in range(len(data)):
Edouard@2152:                             vendor_specific_data += "{:0>2x}".format(ord(data[character]))
Edouard@2152:         data = ""
Edouard@2152:         
Edouard@2152:         #  element3; <EtherCATInfo>-<Descriptions>-<Groups>-<Group>-<Name(LcId is "1033")>
Edouard@2152:         if self.Controler.CTNParent.CTNParent.ModulesLibrary.Library is not None:
Edouard@2152:             for vendorId, vendor in self.Controler.CTNParent.CTNParent.ModulesLibrary.Library.iteritems():
Edouard@2152:                 for group_type, group_etc in vendor["groups"].iteritems():
Edouard@2152:                     for device_item in group_etc["devices"]:
Edouard@2152:                         if device == device_item[1]:
Edouard@2152:                             data = group_etc["name"]
Edouard@2152:         if data is not "" and type(data) == unicode:
Edouard@2152:             for vendor_spec_string in vendor_spec_strings:
Edouard@2152:                 if data == vendor_spec_string:
Edouard@2152:                     groupnameflag = True
Edouard@2152:                     break
Edouard@2152:             if groupnameflag is False:
Edouard@2152:                 count += 1
Edouard@2152:                 self.Strings.append(data)
Edouard@2152:                 vendor_spec_strings.append(data)
Edouard@2152:                 groupnameflag = True
Edouard@2152:                 vendor_specific_data += "{:0>2x}".format(len(data))
Edouard@2152:                 for character in range(len(data)):
Edouard@2152:                     vendor_specific_data += "{:0>2x}".format(ord(data[character]))
Edouard@2152:         data = ""
Edouard@2152:         
Edouard@2152:         #  element4; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Name(LcId is "1033" or "1"?)>
Edouard@2152:         for element in device.getName():
Edouard@2152:             if element.getLcId() == 1 or element.getLcId()==1033:
Edouard@2152:                 data = element.getcontent()
Edouard@2152:         if data is not "" and type(data) == unicode:
Edouard@2152:             for vendor_spec_string in vendor_spec_strings:
Edouard@2152:                 if data == vendor_spec_string:
Edouard@2152:                     self.NameIdx = vendor_spec_strings.index(data)+1
Edouard@2152:                     devnameflag = True
Edouard@2152:                     break
Edouard@2152:             if devnameflag is False:
Edouard@2152:                 count += 1
Edouard@2152:                 self.Strings.append(data)
Edouard@2152:                 vendor_spec_strings.append(data)
Edouard@2152:                 devnameflag = True
Edouard@2152:                 self.NameIdx = count
Edouard@2152:                 vendor_specific_data += "{:0>2x}".format(len(data))
Edouard@2152:                 for character in range(len(data)):
Edouard@2152:                     vendor_specific_data += "{:0>2x}".format(ord(data[character]))
Edouard@2152:         data = ""
Edouard@2152:         
Edouard@2152:         #  element5-1; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Image16x14>
Edouard@2152:         if device.getcontent() is not None:
Edouard@2163:             data = device.getcontent()
Edouard@2152:             if data is not None and type(data) == unicode:
Edouard@2152:                 for vendor_spec_string in vendor_spec_strings:
Edouard@2152:                     if data == vendor_spec_string:
Edouard@2152:                         self.ImgIdx = vendor_spec_strings.index(data)+1
Edouard@2152:                         imageflag = True
Edouard@2152:                         break
Edouard@2152:                 if imageflag is False:
Edouard@2152:                     count += 1
Edouard@2152:                     self.Strings.append(data)
Edouard@2152:                     vendor_spec_strings.append(data)
Edouard@2152:                     imageflag = True
Edouard@2152:                     self.ImgIdx = count
Edouard@2152:                     vendor_specific_data += "{:0>2x}".format(len(data))
Edouard@2152:                     for character in range(len(data)):
Edouard@2152:                         vendor_specific_data += "{:0>2x}".format(ord(data[character]))
Edouard@2152:                         
Edouard@2152:         #  element5-2; <EtherCATInfo>-<Descriptions>-<Groups>-<Group>-<Image16x14>
Edouard@2152:         if imageflag is False:
Edouard@2152:             if self.Controler.CTNParent.CTNParent.ModulesLibrary.Library is not None:
Edouard@2152:                 for vendor_id, vendor in self.Controler.CTNParent.CTNParent.ModulesLibrary.Library.iteritems():
Edouard@2152:                     for group_type, group_etc in vendor["groups"].iteritems():
Edouard@2152:                         for device_item in group_etc["devices"]:
Edouard@2152:                             if device == device_item[1]:
Edouard@2163:                                 data = group_etc
Edouard@2152:                 if data is not None and type(data) == unicode:
Edouard@2152:                     for vendor_spec_string in vendor_spec_strings:
Edouard@2152:                         if data == vendor_spec_string:
Edouard@2152:                             self.ImgIdx = vendor_spec_strings.index(data)+1
Edouard@2152:                             imageflag = True
Edouard@2152:                             break
Edouard@2152:                     if imageflag is False:
Edouard@2152:                         count += 1
Edouard@2152:                         self.Strings.append(data)
Edouard@2152:                         vendor_spec_strings.append(data)
Edouard@2152:                         imageflag = True
Edouard@2152:                         self.ImgIdx = count
Edouard@2152:                         vendor_specific_data += "{:0>2x}".format(len(data))
Edouard@2152:                         for character in range(len(data)):
Edouard@2152:                             vendor_specific_data += "{:0>2x}".format(ord(data[character]))
Edouard@2152:         data = ""
Edouard@2152:         
Edouard@2152:         # DC related elements
Edouard@2152:         #  <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Dc>-<OpMode>-<Name>
Edouard@2152:         dc_related_elements = ""
Edouard@2152:         if device.getDc() is not None:
Edouard@2152:             for element in device.getDc().getOpMode():
Edouard@2152:                 data = element.getName()
Edouard@2152:                 if data is not "":
Edouard@2152:                     count += 1
Edouard@2152:                     self.Strings.append(data)
Edouard@2152:                     dc_related_elements += "{:0>2x}".format(len(data))
Edouard@2152:                     for character in range(len(data)):
Edouard@2152:                         dc_related_elements += "{:0>2x}".format(ord(data[character]))
Edouard@2152:                     data = ""
Edouard@2152:         
Edouard@2152:         # Input elements(TxPDO)
Edouard@2152:         #  <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<TxPdo>; Name
Edouard@2152:         input_elements = ""
Edouard@2152:         inputs = []
Edouard@2152:         for element in device.getTxPdo():
Edouard@2152:             for name in element.getName():
Edouard@2152:                 data = name.getcontent()
Edouard@2152:             for input in inputs:
Edouard@2152:                 if data == input: 
Edouard@2152:                     data = ""
Edouard@2152:             if data is not "":
Edouard@2152:                 count += 1
Edouard@2152:                 self.Strings.append(data)
Edouard@2152:                 inputs.append(data)
Edouard@2152:                 input_elements += "{:0>2x}".format(len(data))
Edouard@2152:                 for character in range(len(data)):
Edouard@2152:                     input_elements += "{:0>2x}".format(ord(data[character]))
Edouard@2152:                 data = ""            
Edouard@2152:             for entry in element.getEntry():
Edouard@2152:                 for name in entry.getName():
Edouard@2152:                     data = name.getcontent()
Edouard@2152:                 for input in inputs:
Edouard@2152:                     if data == input: 
Edouard@2152:                         data = ""
Edouard@2152:                 if data is not "":
Edouard@2152:                     count += 1
Edouard@2152:                     self.Strings.append(data)
Edouard@2152:                     inputs.append(data)
Edouard@2152:                     input_elements += "{:0>2x}".format(len(data))
Edouard@2152:                     for character in range(len(data)):
Edouard@2152:                         input_elements += "{:0>2x}".format(ord(data[character]))
Edouard@2152:                     data = ""
Edouard@2152:         
Edouard@2152:         # Output elements(RxPDO)
Edouard@2152:         #  <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<RxPdo>; Name
Edouard@2152:         output_elements = ""
Edouard@2152:         outputs = []
Edouard@2152:         for element in device.getRxPdo():
Edouard@2152:             for name in element.getName():
Edouard@2152:                 data = name.getcontent()
Edouard@2152:             for output in outputs:
Edouard@2152:                 if data == output: 
Edouard@2152:                     data = ""
Edouard@2152:             if data is not "":
Edouard@2152:                 count += 1
Edouard@2152:                 self.Strings.append(data)
Edouard@2152:                 outputs.append(data)
Edouard@2152:                 output_elements += "{:0>2x}".format(len(data))
Edouard@2152:                 for character in range(len(data)):
Edouard@2152:                     output_elements += "{:0>2x}".format(ord(data[character]))
Edouard@2152:                 data = ""            
Edouard@2152:             for entry in element.getEntry():
Edouard@2152:                 for name in entry.getName():
Edouard@2152:                     data = name.getcontent()
Edouard@2152:                 for output in outputs:
Edouard@2152:                     if data == output: 
Edouard@2152:                         data = ""
Edouard@2152:                 if data is not "":
Edouard@2152:                     count += 1
Edouard@2152:                     self.Strings.append(data)
Edouard@2152:                     outputs.append(data)
Edouard@2152:                     output_elements += "{:0>2x}".format(len(data))
Edouard@2152:                     for character in range(len(data)):
Edouard@2152:                         output_elements += "{:0>2x}".format(ord(data[character]))
Edouard@2152:                     data = ""     
Edouard@2152:         
Edouard@2152:         # form eeprom data
Edouard@2152:         #  category header
Edouard@2152:         eeprom.append("0a")
Edouard@2152:         eeprom.append("00")
Edouard@2152:         #  category length (word); 1 word is 4 bytes. "+2" is the length of string's total number
Edouard@2152:         length = len(vendor_specific_data + dc_related_elements + input_elements + output_elements) + 2
Edouard@2152:         if length%4 == 0:
Edouard@2152:             pass
Edouard@2152:         else:
Edouard@2152:             length +=length%4
Edouard@2152:             padflag = True
Edouard@2152:         eeprom.append("{:0>4x}".format(length/4)[2:4])
Edouard@2152:         eeprom.append("{:0>4x}".format(length/4)[0:2])
Edouard@2152:         #  total numbers of strings
Edouard@2152:         eeprom.append("{:0>2x}".format(count))
Edouard@2152:         for element in [vendor_specific_data,
Edouard@2152:                         dc_related_elements,
Edouard@2152:                         input_elements,
Edouard@2152:                         output_elements]:
Edouard@2152:             for iter in range(len(element)/2):
Edouard@2152:                 if element == "":
Edouard@2152:                     eeprom.append("00")
Edouard@2152:                 else:
Edouard@2152:                     eeprom.append(element[0:2])
Edouard@2152:                 element = element[2:len(element)]     
Edouard@2152:         # padding if length is odd bytes 
Edouard@2152:         if padflag is True:
Edouard@2152:             eeprom.append("ff")
Edouard@2152:         
Edouard@2152:         return eeprom
Edouard@2152:     
Edouard@2152:     def ExtractEEPROMGeneralCategory(self, device):
Edouard@2152:         """
Edouard@2152:         Extract "General" category data from slave ESI XML and generate EEPROM image data.
Edouard@2152:         @param device : 'device' object in the slave ESI XML
Edouard@2152:         @return eeprom : "Strings" category EEPROM image data
Edouard@2152:         """ 
Edouard@2152:         eeprom = []
Edouard@2152:         data = ""
Edouard@2152:         
Edouard@2152:         # category header
Edouard@2152:         eeprom.append("1e")
Edouard@2152:         eeprom.append("00")
Edouard@2152:         
Edouard@2152:         # category length
Edouard@2152:         eeprom.append("10")
Edouard@2152:         eeprom.append("00")
Edouard@2152:         
Edouard@2152:         # word 1 : Group Type index and Image index in STRINGS Category
Edouard@2152:         eeprom.append("{:0>2x}".format(self.GroupIdx))
Edouard@2152:         eeprom.append("{:0>2x}".format(self.ImgIdx))
Edouard@2152:         
Edouard@2152:         # word 2 : Device Type index and Device Name index in STRINGS Category
Edouard@2152:         eeprom.append("{:0>2x}".format(self.OrderIdx))
Edouard@2152:         eeprom.append("{:0>2x}".format(self.NameIdx))
Edouard@2152:         
Edouard@2152:         # word 3 : Physical Layer Port info. and CoE Details
Edouard@2152:         eeprom.append("01") # Physical Layer Port info - assume 01
Edouard@2152:         #  CoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<CoE>
Edouard@2152:         coe_details = 0
Edouard@2163:         mb = device.getMailbox()
Edouard@2163:         coe_details = 1 # sdo enabled
Edouard@2163:         if mb is not None :
Edouard@2163:             coe = mb.getCoE()
Edouard@2163:             if coe is not None:
Edouard@2163:                 for bit,flag in enumerate(["SdoInfo", "PdoAssign", "PdoConfig", 
Edouard@2163:                                            "PdoUpload", "CompleteAccess"]):
Edouard@2163:                     if getattr(coe,"get%s"%flag)() is not None:
Edouard@2163:                         coe_details += 1<<bit        
Edouard@2152:         eeprom.append("{:0>2x}".format(coe_details))
Edouard@2152:         
Edouard@2152:         # word 4 : FoE Details and EoE Details
Edouard@2152:         #  FoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<FoE>
Edouard@2163:         if mb is not None and mb.getFoE() is not None:
Edouard@2152:             eeprom.append("01")
Edouard@2152:         else:
Edouard@2152:             eeprom.append("00")
Edouard@2152:         #  EoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<EoE>
Edouard@2163:         if mb is not None and mb.getEoE() is not None:
Edouard@2152:             eeprom.append("01")
Edouard@2152:         else:
Edouard@2152:             eeprom.append("00")
Edouard@2152:             
Edouard@2152:         # word 5 : SoE Channels(reserved) and DS402 Channels
Edouard@2152:         #  SoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<SoE>
Edouard@2163:         if mb is not None and mb.getSoE() is not None:
Edouard@2152:             eeprom.append("01")
Edouard@2152:         else:
Edouard@2152:             eeprom.append("00")
Edouard@2152:         #  DS402Channels; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<CoE>: DS402Channels
Edouard@2163:         ds402ch = False
Edouard@2163:         if mb is not None :
Edouard@2163:             coe = mb.getCoE()
Edouard@2163:             if coe is not None :
Edouard@2163:                 ds402ch = coe.getDS402Channels()
Edouard@2163:         eeprom.append("01" if ds402ch in [True,1] else "00")
Edouard@2152:             
Edouard@2152:         # word 6 : SysmanClass(reserved) and Flags
Edouard@2152:         eeprom.append("00") # reserved
Edouard@2152:         #  Flags 
Edouard@2152:         en_safeop = False
Edouard@2152:         en_lrw = False
Edouard@2152:         if device.getType().getTcCfgModeSafeOp() == True \
Edouard@2152:         or device.getType().getTcCfgModeSafeOp() == 1:
Edouard@2152:             en_safeop = True
Edouard@2152:         if device.getType().getUseLrdLwr() == True \
Edouard@2152:         or device.getType().getUseLrdLwr() == 1:
Edouard@2152:             en_lrw = True
Edouard@2152:         
Edouard@2152:         flags = "0b"+"000000"+str(int(en_lrw))+str(int(en_safeop))
Edouard@2152:         eeprom.append("{:0>2x}".format(int(flags, 2)))
Edouard@2152:             
Edouard@2152:         # word 7 : Current On EBus (assume 0x0000)
Edouard@2152:         eeprom.append("00")
Edouard@2152:         eeprom.append("00")
Edouard@2152:         # after word 7; couldn't analyze yet
Edouard@2152:         eeprom.append("03")
Edouard@2152:         eeprom.append("00")
Edouard@2152:         eeprom.append("11")
Edouard@2152:         eeprom.append("00")
Edouard@2152:         eeprom.append("00")
Edouard@2152:         eeprom.append("00")
Edouard@2152:         eeprom.append("00")
Edouard@2152:         eeprom.append("00")
Edouard@2152:         eeprom.append("00")
Edouard@2152:         eeprom.append("00")
Edouard@2152:         eeprom.append("00")
Edouard@2152:         eeprom.append("00")
Edouard@2152:         eeprom.append("00")
Edouard@2152:         eeprom.append("00")
Edouard@2152:         eeprom.append("00")
Edouard@2152:         eeprom.append("00")
Edouard@2152:         eeprom.append("00")
Edouard@2152:         eeprom.append("00")
Edouard@2152:         
Edouard@2152:         return eeprom
Edouard@2152:     
Edouard@2152:     def ExtractEEPROMFMMUCategory(self, device):
Edouard@2152:         """
Edouard@2152:         Extract "FMMU" category data from slave ESI XML and generate EEPROM image data.
Edouard@2152:         @param device : 'device' object in the slave ESI XML
Edouard@2152:         @return eeprom : "Strings" category EEPROM image data
Edouard@2152:         """ 
Edouard@2152:         eeprom = []
Edouard@2152:         data = ""
Edouard@2152:         count = 0 # number of FMMU
Edouard@2152:         padflag = False
Edouard@2152:         
Edouard@2152:         for fmmu in device.getFmmu():
Edouard@2152:             count += 1
Edouard@2152:             if fmmu.getcontent() == "Outputs":
Edouard@2152:                 data += "01"
Edouard@2152:             if fmmu.getcontent() == "Inputs":
Edouard@2152:                 data += "02"
Edouard@2152:             if fmmu.getcontent() == "MBoxState":
Edouard@2152:                 data += "03"
Edouard@2152:         
Edouard@2152:         # construct of EEPROM data
Edouard@2152:         if data is not "":
Edouard@2152:             #  category header
Edouard@2152:             eeprom.append("28")
Edouard@2152:             eeprom.append("00")
Edouard@2152:             #  category length
Edouard@2152:             if count%2 == 1:
Edouard@2152:                 padflag = True
Edouard@2152:                 eeprom.append("{:0>4x}".format((count+1)/2)[2:4])
Edouard@2152:                 eeprom.append("{:0>4x}".format((count+1)/2)[0:2])
Edouard@2152:             else: 
Edouard@2152:                 eeprom.append("{:0>4x}".format((count)/2)[2:4])
Edouard@2152:                 eeprom.append("{:0>4x}".format((count)/2)[0:2])
Edouard@2152:             for i in range(count):
Edouard@2152:                 if data == "":
Edouard@2152:                     eeprom.append("00")
Edouard@2152:                 else:
Edouard@2152:                     eeprom.append(data[0:2])
Edouard@2152:                 data = data[2:len(data)]
Edouard@2152:             #  padding if length is odd bytes 
Edouard@2152:             if padflag is True:
Edouard@2152:                 eeprom.append("ff")       
Edouard@2152:             
Edouard@2152:         return eeprom
Edouard@2152:     
Edouard@2152:     def ExtractEEPROMSyncMCategory(self, device):
Edouard@2152:         """
Edouard@2152:         Extract "SyncM" category data from slave ESI XML and generate EEPROM image data.
Edouard@2152:         @param device : 'device' object in the slave ESI XML
Edouard@2152:         @return eeprom : "Strings" category EEPROM image data
Edouard@2152:         """ 
Edouard@2152:         eeprom = []
Edouard@2152:         data = ""
Edouard@2152:         number = {"MBoxOut":"01", "MBoxIn":"02", "Outputs":"03", "Inputs":"04"}
Edouard@2152:         
Edouard@2152:         for sm in device.getSm():
Edouard@2152:             for attr in [sm.getStartAddress(),
Edouard@2152:                          sm.getDefaultSize(),
Edouard@2152:                          sm.getControlByte()]:
Edouard@2152:                 if attr is not None:
Edouard@2152:                     data += "{:0>4x}".format(ExtractHexDecValue(attr))[2:4]
Edouard@2152:                     data += "{:0>4x}".format(ExtractHexDecValue(attr))[0:2]
Edouard@2152:                 else:
Edouard@2152:                     data += "0000"  
Edouard@2152:             if sm.getEnable() == "1" or sm.getEnable() == True:
Edouard@2152:                 data += "01"
Edouard@2152:             else:
Edouard@2152:                 data += "00"
Edouard@2152:             data += number[sm.getcontent()]
Edouard@2152:             
Edouard@2152:         if data is not "":
Edouard@2152:             #  category header
Edouard@2152:             eeprom.append("29")
Edouard@2152:             eeprom.append("00")
Edouard@2152:             #  category length 
Edouard@2152:             eeprom.append("{:0>4x}".format(len(data)/4)[2:4])
Edouard@2152:             eeprom.append("{:0>4x}".format(len(data)/4)[0:2])
Edouard@2152:             for i in range(len(data)/2):
Edouard@2152:                 if data == "":
Edouard@2152:                     eeprom.append("00")
Edouard@2152:                 else:
Edouard@2152:                     eeprom.append(data[0:2])
Edouard@2152:                 data = data[2:len(data)]
Edouard@2152: 
Edouard@2152:         return eeprom
Edouard@2152:     
Edouard@2152:     def ExtractEEPROMPDOCategory(self, device, pdotype):
Edouard@2152:         """
Edouard@2152:         Extract ""PDO (Tx, Rx)"" category data from slave ESI XML and generate EEPROM image data.
Edouard@2152:         @param device : 'device' object in the slave ESI XML
Edouard@2152:         @param pdotype : identifier whether "TxPDO" or "RxPDO".
Edouard@2152:         @return eeprom : "Strings" category EEPROM image data
Edouard@2152:         """ 
Edouard@2152:         eeprom = []
Edouard@2152:         data = ""
Edouard@2152:         count = 0
Edouard@2152:         en_fixed = False
Edouard@2152:         en_mandatory = False
Edouard@2152:         en_virtual = False
Edouard@2152:         
Edouard@2152:         for element in eval("device.get%s()"%pdotype):
Edouard@2152:             #  PDO Index
Edouard@2152:             data += "{:0>4x}".format(ExtractHexDecValue(element.getIndex().getcontent()))[2:4]
Edouard@2152:             data += "{:0>4x}".format(ExtractHexDecValue(element.getIndex().getcontent()))[0:2]
Edouard@2152:             #  Number of Entries
Edouard@2152:             data += "{:0>2x}".format(len(element.getEntry()))
Edouard@2152:             #  About Sync Manager
Edouard@2152:             if element.getSm() is not None:
Edouard@2152:                 data += "{:0>2x}".format(element.getSm())
Edouard@2152:             else:
Edouard@2152:                 data += "ff"
Edouard@2152:             #  Reference to DC Synch (according to ET1100 documentation) - assume 0
Edouard@2152:             data += "00"
Edouard@2152:             #  Name Index
Edouard@2152:             objname = ""
Edouard@2152:             for name in element.getName():
Edouard@2152:                 objname = name.getcontent()
Edouard@2152:             for name in self.Strings:
Edouard@2152:                 count += 1
Edouard@2152:                 if objname == name:
Edouard@2152:                     break
Edouard@2152:             if len(self.Strings)+1 == count:
Edouard@2152:                 data += "00"
Edouard@2152:             else:
Edouard@2152:                 data += "{:0>2x}".format(count)
Edouard@2152:             count = 0
Edouard@2152:             #  Flags; by Fixed, Mandatory, Virtual attributes ?
Edouard@2152:             if element.getFixed() == True or 1:
Edouard@2152:                 en_fixed = True
Edouard@2152:             if element.getMandatory() == True or 1:
Edouard@2152:                 en_mandatory = True
Edouard@2152:             if element.getVirtual() == True or element.getVirtual():
Edouard@2152:                 en_virtual = True
Edouard@2152:             data += str(int(en_fixed)) + str(int(en_mandatory)) + str(int(en_virtual)) + "0"
Edouard@2152:             
Edouard@2152:             for entry in element.getEntry():
Edouard@2152:                 #   Entry Index
Edouard@2152:                 data += "{:0>4x}".format(ExtractHexDecValue(entry.getIndex().getcontent()))[2:4]
Edouard@2152:                 data += "{:0>4x}".format(ExtractHexDecValue(entry.getIndex().getcontent()))[0:2]
Edouard@2152:                 #   Subindex
Edouard@2152:                 data += "{:0>2x}".format(int(entry.getSubIndex()))
Edouard@2152:                 #   Entry Name Index
Edouard@2152:                 objname = ""
Edouard@2152:                 for name in entry.getName():
Edouard@2152:                     objname = name.getcontent()
Edouard@2152:                 for name in self.Strings:
Edouard@2152:                     count += 1
Edouard@2152:                     if objname == name:
Edouard@2152:                         break
Edouard@2152:                 if len(self.Strings)+1 == count:
Edouard@2152:                     data += "00"
Edouard@2152:                 else:
Edouard@2152:                     data += "{:0>2x}".format(count)
Edouard@2152:                 count = 0
Edouard@2152:                 #   DataType
Edouard@2152:                 if entry.getDataType() is not None:
Edouard@2152:                     if entry.getDataType().getcontent() in self.BaseDataTypeDict:
Edouard@2152:                         data += self.BaseDataTypeDict[entry.getDataType().getcontent()]
Edouard@2152:                     else:
Edouard@2152:                         data += "00"
Edouard@2152:                 else:
Edouard@2152:                     data += "00"
Edouard@2152:                 #   BitLen
Edouard@2152:                 if entry.getBitLen() is not None:
Edouard@2152:                     data += "{:0>2x}".format(int(entry.getBitLen()))
Edouard@2152:                 else:
Edouard@2152:                     data += "00"
Edouard@2152:                 #   Flags; by Fixed attributes ?
Edouard@2152:                 en_fixed = False
Edouard@2152:                 if entry.getFixed() == True or entry.getFixed() == 1:
Edouard@2152:                     en_fixed = True
Edouard@2152:                 data += str(int(en_fixed)) + "000"
Edouard@2152:         
Edouard@2152:         if data is not "":
Edouard@2152:             #  category header
Edouard@2152:             if pdotype == "TxPdo":
Edouard@2152:                 eeprom.append("32")
Edouard@2152:             elif pdotype == "RxPdo":
Edouard@2152:                 eeprom.append("33")
Edouard@2152:             else:
Edouard@2152:                 eeprom.append("00")
Edouard@2152:             eeprom.append("00")
Edouard@2152:             #  category length 
Edouard@2152:             eeprom.append("{:0>4x}".format(len(data)/4)[2:4])
Edouard@2152:             eeprom.append("{:0>4x}".format(len(data)/4)[0:2])
Edouard@2152:             data = str(data.lower())
Edouard@2152:             for i in range(len(data)/2):
Edouard@2152:                 if data == "":
Edouard@2152:                     eeprom.append("00")
Edouard@2152:                 else:
Edouard@2152:                     eeprom.append(data[0:2])
Edouard@2152:                 data = data[2:len(data)]
Edouard@2152:         
Edouard@2152:         return eeprom
Edouard@2152:     
Edouard@2152:     def ExtractEEPROMDCCategory(self, device):
Edouard@2152:         """
Edouard@2152:         Extract "DC(Distributed Clock)" category data from slave ESI XML and generate EEPROM image data.
Edouard@2152:         @param device : 'device' object in the slave ESI XML
Edouard@2152:         @return eeprom : "Strings" category EEPROM image data
Edouard@2152:         """ 
Edouard@2152:         eeprom = []
Edouard@2152:         data = ""
Edouard@2152:         count = 0
Edouard@2152:         namecount = 0
Edouard@2152:         
Edouard@2152:         if device.getDc() is not None:
Edouard@2152:             for element in device.getDc().getOpMode():
Edouard@2152:                 count += 1
Edouard@2152:                 #  assume that word 1-7 are 0x0000
Edouard@2152:                 data += "0000"
Edouard@2152:                 data += "0000"
Edouard@2152:                 data += "0000"
Edouard@2152:                 data += "0000"
Edouard@2152:                 data += "0000"
Edouard@2152:                 data += "0000"
Edouard@2152:                 data += "0000"
Edouard@2152:                 #  word 8-10
Edouard@2152:                 #  AssignActivate
Edouard@2152:                 if element.getAssignActivate() is not None:
Edouard@2152:                     data += "{:0>4x}".format(ExtractHexDecValue(element.getAssignActivate()))[2:4]
Edouard@2152:                     data += "{:0>4x}".format(ExtractHexDecValue(element.getAssignActivate()))[0:2]
Edouard@2152:                 else:
Edouard@2152:                     data += "0000"
Edouard@2152:                 #  Factor of CycleTimeSync0 ? and default is 1?
Edouard@2152:                 if element.getCycleTimeSync0() is not None:
Edouard@2152:                     if element.getCycleTimeSync0().getFactor() is not None:
Edouard@2152:                         data += "{:0>2x}".format(int(element.getCycleTimeSync0().getFactor()))
Edouard@2152:                         data += "00"
Edouard@2152:                     else:
Edouard@2152:                         data += "0100"
Edouard@2152:                 else:
Edouard@2152:                     data += "0100"
Edouard@2152:                 #  Index of Name in STRINGS Category
Edouard@2152:                 #  Name Index
Edouard@2152:                 objname = ""
Edouard@2152:                 for name in element.getName():
Edouard@2152:                     objname += name
Edouard@2152:                 for name in self.Strings:
Edouard@2152:                     namecount += 1
Edouard@2152:                     if objname == name:
Edouard@2152:                         break
Edouard@2152:                 if len(self.Strings)+1 == namecount:
Edouard@2152:                     data += "00"
Edouard@2152:                 else:
Edouard@2152:                     data += "{:0>2x}".format(namecount)
Edouard@2152:                 namecount = 0
Edouard@2152:                 data += "00"
Edouard@2152:                 #  assume that word 11-12 are 0x0000
Edouard@2152:                 data += "0000"
Edouard@2152:                 data += "0000"
Edouard@2152:                 
Edouard@2152:         if data is not "":
Edouard@2152:             #  category header
Edouard@2152:             eeprom.append("3c")
Edouard@2152:             eeprom.append("00")
Edouard@2152:             #  category length 
Edouard@2152:             eeprom.append("{:0>4x}".format(len(data)/4)[2:4])
Edouard@2152:             eeprom.append("{:0>4x}".format(len(data)/4)[0:2])
Edouard@2152:             data = str(data.lower())
Edouard@2152:             for i in range(len(data)/2):
Edouard@2152:                 if data == "":
Edouard@2152:                     eeprom.append("00")
Edouard@2152:                 else:
Edouard@2152:                     eeprom.append(data[0:2])
Edouard@2152:                 data = data[2:len(data)]
Edouard@2152:     
Edouard@2152:         return eeprom
Edouard@2152:     
Edouard@2152:     #-------------------------------------------------------------------------------
Edouard@2152:     #                        Used Register Access
Edouard@2152:     #-------------------------------------------------------------------------------
Edouard@2152:     def RegRead(self, offset, length):
Edouard@2152:         """
Edouard@2152:         Read slave ESC register content using "ethercat reg_read -p %d %s %s" command.
Edouard@2152:         Command example : "ethercat reg_read -p 0 0x0c00 0x0400"
Edouard@2152:         @param offset : register address
Edouard@2152:         @param length : register length
Edouard@2152:         @return return_val : register data
Edouard@2152:         """ 
Edouard@2152:         error, return_val = self.Controler.RemoteExec(REG_READ%(self.Controler.GetSlavePos(), offset, length), return_val = None)
Edouard@2152:         return return_val   
Edouard@2152:     
Edouard@2152:     def RegWrite(self, address, data):
Edouard@2152:         """
Edouard@2152:         Write data to slave ESC register using "ethercat reg_write -p %d %s %s" command.
Edouard@2152:         Command example : "ethercat reg_write -p 0 0x0c04 0x0001"
Edouard@2152:         @param address : register address
Edouard@2152:         @param data : data to write
Edouard@2152:         @return return_val : the execution result of "ethercat reg_write" (for error check)
Edouard@2152:         """ 
Edouard@2152:         error, return_val = self.Controler.RemoteExec(REG_WRITE%(self.Controler.GetSlavePos(), address, data), return_val = None)
Edouard@2152:         return return_val 
Edouard@2152:     
Edouard@2152:     def Rescan(self):
Edouard@2152:         """
Edouard@2152:         Synchronize EEPROM data in master controller with the data in slave device after EEPROM write.
Edouard@2152:         Command example : "ethercat rescan -p 0"
Edouard@2152:         """ 
Edouard@2152:         error, return_val = self.Controler.RemoteExec(RESCAN%(self.Controler.GetSlavePos()), return_val = None)
Edouard@2152:     
Edouard@2152:     #-------------------------------------------------------------------------------
Edouard@2152:     #                        Common Use Methods
Edouard@2152:     #-------------------------------------------------------------------------------
Edouard@2152:     def CheckConnect(self, cyclic_flag):
Edouard@2152:         """
Edouard@2152:         Check connection status (1) between Beremiz and the master (2) between the master and the slave. 
Edouard@2152:         @param cyclic_flag: 0 - one shot, 1 - periodic
Edouard@2152:         @return True or False
Edouard@2152:         """ 
Edouard@2152:         if self.Controler.GetCTRoot()._connector is not None:
Edouard@2152:             # Check connection between the master and the slave. 
Edouard@2152:             # Command example : "ethercat xml -p 0"
Edouard@2152:             error, return_val = self.Controler.RemoteExec(SLAVE_XML%(self.Controler.GetSlavePos()), return_val = None)
Edouard@2152:             number_of_lines = return_val.split("\n")
Edouard@2152:             if len(number_of_lines) <= 2 :  # No slave connected to the master controller
Edouard@2152:                 if not cyclic_flag :
Edouard@2152:                     self.CreateErrorDialog('No connected slaves')
Edouard@2152:                 return False
Edouard@2152:         
Edouard@2152:             elif len(number_of_lines) > 2 :
Edouard@2152:                 return True
Edouard@2152:         else:                               
Edouard@2152:             # The master controller is not connected to Beremiz host
Edouard@2152:             if not cyclic_flag :
Edouard@2152:                 self.CreateErrorDialog('PLC not connected!')
Edouard@2152:             return False
Edouard@2152:         
Edouard@2152:     def CreateErrorDialog(self, mention):
Edouard@2152:         """
Edouard@2152:         Create a dialog to indicate error or warning.
Edouard@2152:         @param mention : Error String
Edouard@2152:         """ 
Edouard@2152:         app_frame = self.Controler.GetCTRoot().AppFrame
Edouard@2152:         dlg = wx.MessageDialog (app_frame, mention, 
Edouard@2152:                                 ' Warning...', 
Edouard@2152:                                 wx.OK | wx.ICON_INFORMATION)
Edouard@2152:         dlg.ShowModal()
Edouard@2152:         dlg.Destroy()