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; -- 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; -- address 0x00 Edouard@2152: smartview_infos["pdi_type"] = int(configData_data[0:2], 16) Edouard@2152: # get state of device emulation; -- 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; -- 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; - 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; - 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 - 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; -- 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; -- 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; - 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<---- 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; ---- 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; --- 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; ---- 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; ---- 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; ---- 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; ---- 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: # ------ 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: # ----; 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: # ----; 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; ----- 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<2x}".format(coe_details)) Edouard@2152: Edouard@2152: # word 4 : FoE Details and EoE Details Edouard@2152: # FoE Details; ----- 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; ----- 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; ----- 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; -----: 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()