# HG changeset patch # User Andrey Skvortsov # Date 1538144411 -10800 # Node ID fec77f2b9e0713a14287895303e552dec5ffa5b9 # Parent 9460872f1440ab300f0cb6ee9d94a9396b96e018 cleanup etherlab: pep8, W291 trailing whitespace diff -r 9460872f1440 -r fec77f2b9e07 etherlab/CommonEtherCATFunction.py --- a/etherlab/CommonEtherCATFunction.py Fri Sep 28 17:15:53 2018 +0300 +++ b/etherlab/CommonEtherCATFunction.py Fri Sep 28 17:20:11 2018 +0300 @@ -25,7 +25,7 @@ pass try: return int(value.replace("#", "0"), 16) - + except Exception: raise ValueError, "Invalid value for HexDecValue \"%s\"" % value @@ -52,7 +52,7 @@ MASTER_STATE = """ import commands result = commands.getoutput("ethercat master") -returnVal =result +returnVal =result """ # --------------------- for slave ---------------------------- @@ -60,84 +60,84 @@ SLAVE_STATE = """ import commands result = commands.getoutput("ethercat state -p %d %s") -returnVal = result +returnVal = result """ # ethercat slave GET_SLAVE = """ import commands result = commands.getoutput("ethercat slaves") -returnVal =result +returnVal =result """ # ethercat xml -p (slave position) SLAVE_XML = """ import commands result = commands.getoutput("ethercat xml -p %d") -returnVal = result +returnVal = result """ # ethercat sdos -p (slave position) SLAVE_SDO = """ import commands result = commands.getoutput("ethercat sdos -p %d") -returnVal =result +returnVal =result """ # ethercat upload -p (slave position) (main index) (sub index) GET_SLOW_SDO = """ import commands result = commands.getoutput("ethercat upload -p %d %s %s") -returnVal =result +returnVal =result """ # ethercat download -p (slave position) (main index) (sub index) (value) SDO_DOWNLOAD = """ import commands result = commands.getoutput("ethercat download --type %s -p %d %s %s %s") -returnVal =result +returnVal =result """ # ethercat sii_read -p (slave position) SII_READ = """ import commands result = commands.getoutput("ethercat sii_read -p %d") -returnVal =result +returnVal =result """ # ethercat reg_read -p (slave position) (address) (size) REG_READ = """ import commands result = commands.getoutput("ethercat reg_read -p %d %s %s") -returnVal =result +returnVal =result """ # ethercat sii_write -p (slave position) - (contents) -SII_WRITE = """ -import subprocess +SII_WRITE = """ +import subprocess process = subprocess.Popen( ["ethercat", "-f", "sii_write", "-p", "%d", "-"], stdin=subprocess.PIPE) process.communicate(sii_data) -returnVal = process.returncode +returnVal = process.returncode """ # ethercat reg_write -p (slave position) -t (uinit16) (address) (data) -REG_WRITE = """ +REG_WRITE = """ import commands result = commands.getoutput("ethercat reg_write -p %d -t uint16 %s %s") -returnVal =result -""" +returnVal =result +""" # ethercat rescan -p (slave position) -RESCAN = """ +RESCAN = """ import commands result = commands.getoutput("ethercat rescan -p %d") -returnVal =result +returnVal =result """ #-------------------------------------------------- -# Common Method For EtherCAT Management +# Common Method For EtherCAT Management #-------------------------------------------------- class _CommonSlave: @@ -147,11 +147,11 @@ # category of SDO data DatatypeDescription, CommunicationObject, ManufacturerSpecific, \ ProfileSpecific, Reserved, AllSDOData = range(6) - + # store the execution result of "ethercat sdos" command into SaveSDOData. SaveSDOData = [] - - # Flags for checking "write" permission of OD entries + + # Flags for checking "write" permission of OD entries CheckPREOP = False CheckSAFEOP = False CheckOP = False @@ -161,7 +161,7 @@ TxPDOCategory = [] RxPDOInfo = [] RxPDOCategory = [] - + # Save EEPROM Data SiiData = "" @@ -171,26 +171,26 @@ "FMMUNumber": "", "SMNumber": "", "PDIType": ""} - + def __init__(self, controler): """ Constructor @param controler: _EthercatSlaveCTN class in EthercatSlave.py """ self.Controler = controler - + self.ClearSDODataSet() - + #------------------------------------------------------------------------------- # Used Master State #------------------------------------------------------------------------------- def GetMasterState(self): """ Execute "ethercat master" command and parse the execution result - @return MasterState - """ - - # exectute "ethercat master" command + @return MasterState + """ + + # exectute "ethercat master" command error, return_val = self.Controler.RemoteExec(MASTER_STATE, return_val = None) master_state = {} # parse the reslut @@ -204,9 +204,9 @@ if '(attached)' in value: value.remove('(attached)') master_state[key] = value - - return master_state - + + return master_state + #------------------------------------------------------------------------------- # Used Slave State #------------------------------------------------------------------------------- @@ -214,19 +214,19 @@ """ Set slave state to the specified one using "ethercat states -p %d %s" command. Command example : "ethercat states -p 0 PREOP" (target slave position and target state are given.) - @param command : target slave state + @param command : target slave state """ error, return_val = self.Controler.RemoteExec(SLAVE_STATE%(self.Controler.GetSlavePos(), command), return_val = None) - - def GetSlaveStateFromSlave(self): - """ - Get slave information using "ethercat slaves" command and store the information into internal data structure - (self.SlaveState) for "Slave State" + + def GetSlaveStateFromSlave(self): + """ + Get slave information using "ethercat slaves" command and store the information into internal data structure + (self.SlaveState) for "Slave State" return_val example : 0 0:0 PREOP + EL9800 (V4.30) (PIC24, SPI, ET1100) - """ + """ error, return_val = self.Controler.RemoteExec(GET_SLAVE, return_val = None) self.SlaveState = return_val - return return_val + return return_val #------------------------------------------------------------------------------- # Used SDO Management @@ -236,10 +236,10 @@ Get SDO objects information of current slave using "ethercat sdos -p %d" command. Command example : "ethercat sdos -p 0" @return return_val : execution results of "ethercat sdos" command (need to be parsed later) - """ + """ error, return_val = self.Controler.RemoteExec(SLAVE_SDO%(self.Controler.GetSlavePos()), return_val = None) - return return_val - + return return_val + def SDODownload(self, data_type, idx, sub_idx, value): """ Set an SDO object value to user-specified value using "ethercat download" command. @@ -248,64 +248,64 @@ @param idx : index of the SDO entry @param sub_idx : subindex of the SDO entry @param value : value of SDO entry - """ + """ error, return_val = self.Controler.RemoteExec(SDO_DOWNLOAD%(data_type, self.Controler.GetSlavePos(), idx, sub_idx, value), return_val = None) - + def BackupSDODataSet(self): """ - Back-up current SDO entry information to restore the SDO data + Back-up current SDO entry information to restore the SDO data in case that the user cancels SDO update operation. - """ + """ self.BackupDatatypeDescription = self.SaveDatatypeDescription self.BackupCommunicationObject = self.SaveCommunicationObject self.BackupManufacturerSpecific = self.SaveManufacturerSpecific self.BackupProfileSpecific = self.SaveProfileSpecific self.BackupReserved = self.SaveReserved self.BackupAllSDOData = self.SaveAllSDOData - + def ClearSDODataSet(self): """ Clear the specified SDO entry information. - """ + """ for count in range(6): self.SaveSDOData.append([]) - + #------------------------------------------------------------------------------- # Used PDO Monitoring #------------------------------------------------------------------------------- def RequestPDOInfo(self): """ Load slave information from RootClass (XML data) and parse the information (calling SlavePDOData() method). - """ + """ # Load slave information from ESI XML file (def EthercatMaster.py) slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos()) - + type_infos = slave.getType() device, alignment = self.Controler.CTNParent.GetModuleInfos(type_infos) # Initialize PDO data set self.ClearDataSet() - - # if 'device' object is valid, call SavePDOData() to parse PDO data + + # if 'device' object is valid, call SavePDOData() to parse PDO data if device is not None : self.SavePDOData(device) - + def SavePDOData(self, device): """ Parse PDO data and store the results in TXPDOCategory and RXPDOCategory Tx(Rx)PDOCategory : index, name, entry number Tx(Rx)Info : entry index, sub index, name, length, type @param device : Slave information extracted from ESI XML file - """ + """ # Parsing TXPDO entries for pdo, pdo_info in ([(pdo, "Inputs") for pdo in device.getTxPdo()]): # Save pdo_index, entry, and name of each entry pdo_index = ExtractHexDecValue(pdo.getIndex().getcontent()) entries = pdo.getEntry() pdo_name = ExtractName(pdo.getName()) - + # Initialize entry number count count = 0 - + # Parse entries for entry in entries: # Save index and subindex @@ -322,8 +322,8 @@ } self.TxPDOInfo.append(entry_infos) count += 1 - - categorys = {"pdo_index" : pdo_index, "name" : pdo_name, "number_of_entry" : count} + + categorys = {"pdo_index" : pdo_index, "name" : pdo_name, "number_of_entry" : count} self.TxPDOCategory.append(categorys) # Parsing RxPDO entries @@ -332,11 +332,11 @@ pdo_index = ExtractHexDecValue(pdo.getIndex().getcontent()) entries = pdo.getEntry() pdo_name = ExtractName(pdo.getName()) - + # Initialize entry number count - count = 0 - - # Parse entries + count = 0 + + # Parse entries for entry in entries: # Save index and subindex index = ExtractHexDecValue(entry.getIndex().getcontent()) @@ -352,51 +352,51 @@ } self.RxPDOInfo.append(entry_infos) count += 1 - - categorys = {"pdo_index" : pdo_index, "name" : pdo_name, "number_of_entry" : count} - self.RxPDOCategory.append(categorys) + + categorys = {"pdo_index" : pdo_index, "name" : pdo_name, "number_of_entry" : count} + self.RxPDOCategory.append(categorys) def GetTxPDOCategory(self): """ Get TxPDOCategory data structure (Meta informaton of TxPDO). TxPDOCategorys : index, name, number of entries @return TxPDOCategorys - """ + """ return self.TxPDOCategory - + def GetRxPDOCategory(self): """ Get RxPDOCategory data structure (Meta information of RxPDO). RxPDOCategorys : index, name, number of entries @return RxPDOCategorys - """ + """ return self.RxPDOCategory - + def GetTxPDOInfo(self): """ - Get TxPDOInfo data structure (Detailed information on TxPDO entries). + Get TxPDOInfo data structure (Detailed information on TxPDO entries). TxPDOInfos : entry index, sub index, name, length, type @return TxPDOInfos - """ + """ return self.TxPDOInfo - + def GetRxPDOInfo(self): """ - Get RxPDOInfo data structure (Detailed information on RxPDO entries). + Get RxPDOInfo data structure (Detailed information on RxPDO entries). RxPDOInfos : entry index, sub index, name, length, type @return RxPDOInfos - """ + """ return self.RxPDOInfo - + def ClearDataSet(self): """ Initialize PDO management data structure. - """ + """ self.TxPDOInfos = [] self.TxPDOCategorys = [] self.RxPDOInfos = [] self.RxPDOCategorys = [] - + #------------------------------------------------------------------------------- # Used EEPROM Management #------------------------------------------------------------------------------- @@ -431,13 +431,13 @@ "BIT5": "34", "BIT6": "35", "BIT7": "36", - "BIT8": "37"} - + "BIT8": "37"} + def GetSmartViewInfos(self): """ Parse XML data for "Smart View" of EEPROM contents. @return smartview_infos : EEPROM contents dictionary - """ + """ smartview_infos = {"eeprom_size": 128, "pdi_type": 0, @@ -455,7 +455,7 @@ "mailbox_standardconf_outlength": '0', "mailbox_standardconf_instart": '0', "mailbox_standardconf_inlength": '0'} - + slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos()) type_infos = slave.getType() device, alignment = self.Controler.CTNParent.GetModuleInfos(type_infos) @@ -466,7 +466,7 @@ # get EEPROM size; -- if eeprom_element["name"] == "ByteSize": smartview_infos["eeprom_size"] = eeprom_element - + elif eeprom_element["name"] == "ConfigData": configData_data = self.DecimalToHex(eeprom_element) # get PDI type; -- address 0x00 @@ -478,12 +478,12 @@ elif eeprom_element["name"] == "BootStrap": bootstrap_data = "{:0>16x}".format(eeprom_element) # get bootstrap configuration; -- - for cfg, iter in [("mailbox_bootstrapconf_outstart", 0), + for cfg, iter in [("mailbox_bootstrapconf_outstart", 0), ("mailbox_bootstrapconf_outlength", 1), ("mailbox_bootstrapconf_instart", 2), ("mailbox_bootstrapconf_inlength", 3)]: smartview_infos[cfg] = str(int(bootstrap_data[4*iter+2:4*(iter+1)]+bootstrap_data[4*iter:4*iter+2], 16)) - + # get protocol (profile) types supported by mailbox; - mb = device.getMailbox() if mb is not None: @@ -491,7 +491,7 @@ if getattr(mb,"get%s"%mailbox_protocol)() is not None: smartview_infos["supported_mailbox"] += "%s, "%mailbox_protocol smartview_infos["supported_mailbox"] = smartview_infos["supported_mailbox"].strip(", ") - + # get standard configuration of mailbox; - for sm_element in device.getSm(): if sm_element.getcontent() == "MBoxOut": @@ -510,42 +510,42 @@ for available_device in vendor["groups"][vendor["groups"].keys()[0]]["devices"]: if available_device[0] == type_infos["device_type"]: smartview_infos["vendor_id"] = "0x" + "{:0>8x}".format(vendor_id) - - # product code; + + # product code; if device.getType().getProductCode() is not None: product_code = device.getType().getProductCode() smartview_infos["product_code"] = "0x"+"{:0>8x}".format(ExtractHexDecValue(product_code)) - - # revision number; + + # revision number; if device.getType().getRevisionNo() is not None: revision_no = device.getType().getRevisionNo() smartview_infos["revision_no"] = "0x"+"{:0>8x}".format(ExtractHexDecValue(revision_no)) - + # serial number; if device.getType().getSerialNo() is not None: serial_no = device.getType().getSerialNo() smartview_infos["serial_no"] = "0x"+"{:0>8x}".format(ExtractHexDecValue(serial_no)) - + return smartview_infos - + else: return None - + def DecimalToHex(self, decnum): """ - Convert decimal value into hexadecimal representation. + Convert decimal value into hexadecimal representation. @param decnum : decimal value @return hex_data : hexadecimal representation of input value in decimal - """ + """ value = "%x" % decnum value_len = len(value) if (value_len % 2) == 0: hex_len = value_len else: hex_len = (value_len / 2) * 2 + 2 - + hex_data = ("{:0>"+str(hex_len)+"x}").format(decnum) - + return hex_data def SiiRead(self): @@ -553,7 +553,7 @@ Get slave EEPROM contents maintained by master device using "ethercat sii_read -p %d" command. Command example : "ethercat sii_read -p 0" @return return_val : result of "ethercat sii_read" (binary data) - """ + """ error, return_val = self.Controler.RemoteExec(SII_READ%(self.Controler.GetSlavePos()), return_val = None) self.SiiData = return_val return return_val @@ -564,15 +564,15 @@ Command example : "ethercat sii_write -p 0 - (binary contents)" @param binary : EEPROM contents in binary data format @return return_val : result of "ethercat sii_write" (If it succeeds, the return value is NULL.) - """ + """ error, return_val = self.Controler.RemoteExec(SII_WRITE%(self.Controler.GetSlavePos()), return_val = None, sii_data = binary) - return return_val + return return_val def LoadData(self): """ Loading data from EEPROM use Sii_Read Method @return self.BinaryCode : slave EEPROM data in binary format (zero-padded) - """ + """ return_val = self.Controler.CommonMethod.SiiRead() self.BinaryCode = return_val self.Controler.SiiData = self.BinaryCode @@ -580,7 +580,7 @@ # append zero-filled padding data up to EEPROM size for index in range(self.SmartViewInfosFromXML["eeprom_size"] - len(self.BinaryCode)): self.BinaryCode = self.BinaryCode +'ff'.decode('hex') - + return self.BinaryCode def HexRead(self, binary): @@ -589,42 +589,42 @@ @param binary : binary digits @return hexCode : hexadecimal digits @return hexview_table_row, hexview_table_col : Grid size for "Hex View" UI - """ + """ row_code = [] row_text = "" row = 0 hex_code = [] hexview_table_col = 17 - + for index in range(0, len(binary)) : if len(binary[index]) != 1: break else: - digithexstr = hex(ord(binary[index])) + digithexstr = hex(ord(binary[index])) tempvar2 = digithexstr[2:4] if len(tempvar2) == 1: tempvar2 = "0" + tempvar2 - row_code.append(tempvar2) - + row_code.append(tempvar2) + if int(digithexstr, 16)>=32 and int(digithexstr, 16)<=126: row_text = row_text + chr(int(digithexstr, 16)) else: row_text = row_text + "." - - if index != 0 : + + if index != 0 : if len(row_code) == (hexview_table_col - 1): row_code.append(row_text) hex_code.append(row_code) row_text = "" row_code = [] - row = row + 1 - + row = row + 1 + hexview_table_row = row - + return hex_code, hexview_table_row, hexview_table_col - + def GenerateEEPROMList(self, data, direction, length): """ Generate EEPROM data list by reconstructing 'data' string. @@ -634,7 +634,7 @@ @param direction : endianness @param length : data length @return eeprom_list : reconstructed list data structure - """ + """ eeprom_list = [] if direction is 0 or 1: @@ -646,7 +646,7 @@ data = data[(1-direction)*2:length-direction*2] length -= 2 return eeprom_list - + def XmlToEeprom(self): """ Extract slave EEPROM contents using slave ESI XML file. @@ -657,8 +657,8 @@ - SyncM category : ExtractEEPROMSyncMCategory() - Tx/RxPDO category : ExtractEEPROMPDOCategory() - DC category : ExtractEEPROMDCCategory() - @return eeprom_binary - """ + @return eeprom_binary + """ eeprom = [] data = "" eeprom_size = 0 @@ -668,14 +668,14 @@ slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos()) type_infos = slave.getType() device, alignment = self.Controler.CTNParent.GetModuleInfos(type_infos) - + if device is not None: # get ConfigData for EEPROM offset 0x0000-0x000d; -- for eeprom_element in device.getEeprom().getcontent(): if eeprom_element["name"] == "ConfigData": data = self.DecimalToHex(eeprom_element) eeprom += self.GenerateEEPROMList(data, 0, 28) - + # calculate CRC for EEPROM offset 0x000e-0x000f crc = 0x48 for segment in eeprom: @@ -683,15 +683,15 @@ bit = crc & 0x80 crc = (crc << 1) | ((int(segment, 16) >> (7 - i)) & 0x01) if bit: - crc ^= 0x07 + crc ^= 0x07 for k in range(8): bit = crc & 0x80 crc <<= 1 if bit: - crc ^= 0x07 + crc ^= 0x07 eeprom.append(hex(crc)[len(hex(crc))-3:len(hex(crc))-1]) eeprom.append("00") - + # get VendorID for EEPROM offset 0x0010-0x0013; data = "" for vendor_id, vendor in self.Controler.CTNParent.CTNParent.ModulesLibrary.Library.iteritems(): @@ -699,35 +699,35 @@ if available_device[0] == type_infos["device_type"]: data = "{:0>8x}".format(vendor_id) eeprom += self.GenerateEEPROMList(data, 1, 8) - + # get Product Code for EEPROM offset 0x0014-0x0017; data = "" if device.getType().getProductCode() is not None: data = "{:0>8x}".format(ExtractHexDecValue(device.getType().getProductCode())) eeprom += self.GenerateEEPROMList(data, 1, 8) - + # get Revision Number for EEPROM offset 0x0018-0x001b; data = "" if device.getType().getRevisionNo() is not None: data = "{:0>8x}".format(ExtractHexDecValue(device.getType().getRevisionNo())) - eeprom += self.GenerateEEPROMList(data, 1, 8) - + eeprom += self.GenerateEEPROMList(data, 1, 8) + # get Serial Number for EEPROM 0x001c-0x001f; data = "" if device.getType().getSerialNo() is not None: data = "{:0>8x}".format(ExtractHexDecValue(device.getType().getSerialNo())) eeprom += self.GenerateEEPROMList(data, 1, 8) - + # get Execution Delay for EEPROM 0x0020-0x0021; not analyzed yet eeprom.append("00") eeprom.append("00") - + # get Port0/1 Delay for EEPROM offset 0x0022-0x0025; not analyzed yet eeprom.append("00") eeprom.append("00") eeprom.append("00") eeprom.append("00") - + # reserved for EEPROM offset 0x0026-0x0027; eeprom.append("00") eeprom.append("00") @@ -738,7 +738,7 @@ if eeprom_element["name"] == "BootStrap": data = "{:0>16x}".format(eeprom_element) eeprom += self.GenerateEEPROMList(data, 0, 16) - + # get Standard Mailbox for EEPROM offset 0x0030-0x0037; - data = "" standard_send_mailbox_offset = None @@ -752,7 +752,7 @@ elif sm_element.getcontent() == "MBoxIn": standard_send_mailbox_offset = "{:0>4x}".format(ExtractHexDecValue(sm_element.getStartAddress())) standard_send_mailbox_size = "{:0>4x}".format(ExtractHexDecValue(sm_element.getDefaultSize())) - + if standard_receive_mailbox_offset is None: eeprom.append("00") eeprom.append("00") @@ -777,7 +777,7 @@ else: eeprom.append(standard_send_mailbox_size[2:4]) eeprom.append(standard_send_mailbox_size[0:2]) - + # get supported mailbox protocols for EEPROM offset 0x0038-0x0039; data = 0 mb = device.getMailbox() @@ -788,11 +788,11 @@ data = "{:0>4x}".format(data) eeprom.append(data[2:4]) eeprom.append(data[0:2]) - + # resereved for EEPROM offset 0x003a-0x007b; for i in range(0x007b-0x003a+0x0001): eeprom.append("00") - + # get EEPROM size for EEPROM offset 0x007c-0x007d; data = "" for eeprom_element in device.getEeprom().getcontent(): @@ -806,76 +806,76 @@ else: eeprom.append(data[2:4]) eeprom.append(data[0:2]) - - # Version for EEPROM 0x007e-0x007f; + + # Version for EEPROM 0x007e-0x007f; # According to "EtherCAT Slave Device Description(V0.3.0)" eeprom.append("01") eeprom.append("00") - + # append String Category data for data in self.ExtractEEPROMStringCategory(device): eeprom.append(data) - + # append General Category data for data in self.ExtractEEPROMGeneralCategory(device): eeprom.append(data) - + # append FMMU Category data for data in self.ExtractEEPROMFMMUCategory(device): eeprom.append(data) - + # append SyncM Category data for data in self.ExtractEEPROMSyncMCategory(device): eeprom.append(data) - + # append TxPDO Category data for data in self.ExtractEEPROMPDOCategory(device, "TxPdo"): eeprom.append(data) - + # append RxPDO Category data for data in self.ExtractEEPROMPDOCategory(device, "RxPdo"): eeprom.append(data) - + # append DC Category data for data in self.ExtractEEPROMDCCategory(device): eeprom.append(data) - + # append padding padding = eeprom_size-len(eeprom) for i in range(padding): eeprom.append("ff") - + # convert binary code for index in range(eeprom_size): eeprom_binary = eeprom_binary + eeprom[index].decode('hex') - + return eeprom_binary - + def ExtractEEPROMStringCategory(self, device): """ Extract "Strings" category data from slave ESI XML and generate EEPROM image data. @param device : 'device' object in the slave ESI XML @return eeprom : "Strings" category EEPROM image data - """ + """ eeprom = [] self.Strings = [] - data = "" + data = "" count = 0 # string counter padflag = False # padding flag if category length is odd - + # index information for General Category in EEPROM self.GroupIdx = 0 self.ImgIdx = 0 self.OrderIdx = 0 self.NameIdx = 0 - - # flag for preventing duplicated vendor specific data + + # flag for preventing duplicated vendor specific data typeflag = False grouptypeflag = False groupnameflag = False devnameflag = False imageflag = False - + # vendor specific data # element1; ---- # vendor_specific_data : vendor specific data (binary type) @@ -885,7 +885,7 @@ for element in device.getType().getcontent(): data += element if data is not "" and type(data) == unicode: - for vendor_spec_string in vendor_spec_strings: + for vendor_spec_string in vendor_spec_strings: if data == vendor_spec_string: self.OrderIdx = vendor_spec_strings.index(data)+1 typeflag = True @@ -900,7 +900,7 @@ for character in range(len(data)): vendor_specific_data += "{:0>2x}".format(ord(data[character])) data = "" - + # element2-1; ---- data = device.getGroupType() if data is not None and type(data) == unicode: @@ -919,14 +919,14 @@ vendor_specific_data += "{:0>2x}".format(len(data)) for character in range(len(data)): vendor_specific_data += "{:0>2x}".format(ord(data[character])) - - # element2-2; --- - if grouptypeflag is False: + + # element2-2; --- + if grouptypeflag is False: if self.Controler.CTNParent.CTNParent.ModulesLibrary.Library is not None: for vendor_id, vendor in self.Controler.CTNParent.CTNParent.ModulesLibrary.Library.iteritems(): for group_type, group_etc in vendor["groups"].iteritems(): for device_item in group_etc["devices"]: - if device == device_item[1]: + if device == device_item[1]: data = group_type if data is not None and type(data) == unicode: for vendor_spec_string in vendor_spec_strings: @@ -945,7 +945,7 @@ for character in range(len(data)): vendor_specific_data += "{:0>2x}".format(ord(data[character])) data = "" - + # element3; ---- if self.Controler.CTNParent.CTNParent.ModulesLibrary.Library is not None: for vendorId, vendor in self.Controler.CTNParent.CTNParent.ModulesLibrary.Library.iteritems(): @@ -967,7 +967,7 @@ for character in range(len(data)): vendor_specific_data += "{:0>2x}".format(ord(data[character])) data = "" - + # element4; ---- for element in device.getName(): if element.getLcId() == 1 or element.getLcId()==1033: @@ -988,7 +988,7 @@ for character in range(len(data)): vendor_specific_data += "{:0>2x}".format(ord(data[character])) data = "" - + # element5-1; ---- if device.getcontent() is not None: data = device.getcontent() @@ -1007,7 +1007,7 @@ vendor_specific_data += "{:0>2x}".format(len(data)) for character in range(len(data)): vendor_specific_data += "{:0>2x}".format(ord(data[character])) - + # element5-2; ---- if imageflag is False: if self.Controler.CTNParent.CTNParent.ModulesLibrary.Library is not None: @@ -1032,7 +1032,7 @@ for character in range(len(data)): vendor_specific_data += "{:0>2x}".format(ord(data[character])) data = "" - + # DC related elements # ------ dc_related_elements = "" @@ -1046,7 +1046,7 @@ for character in range(len(data)): dc_related_elements += "{:0>2x}".format(ord(data[character])) data = "" - + # Input elements(TxPDO) # ----; Name input_elements = "" @@ -1055,7 +1055,7 @@ for name in element.getName(): data = name.getcontent() for input in inputs: - if data == input: + if data == input: data = "" if data is not "": count += 1 @@ -1064,12 +1064,12 @@ input_elements += "{:0>2x}".format(len(data)) for character in range(len(data)): input_elements += "{:0>2x}".format(ord(data[character])) - data = "" + data = "" for entry in element.getEntry(): for name in entry.getName(): data = name.getcontent() for input in inputs: - if data == input: + if data == input: data = "" if data is not "": count += 1 @@ -1079,7 +1079,7 @@ for character in range(len(data)): input_elements += "{:0>2x}".format(ord(data[character])) data = "" - + # Output elements(RxPDO) # ----; Name output_elements = "" @@ -1088,7 +1088,7 @@ for name in element.getName(): data = name.getcontent() for output in outputs: - if data == output: + if data == output: data = "" if data is not "": count += 1 @@ -1097,12 +1097,12 @@ output_elements += "{:0>2x}".format(len(data)) for character in range(len(data)): output_elements += "{:0>2x}".format(ord(data[character])) - data = "" + data = "" for entry in element.getEntry(): for name in entry.getName(): data = name.getcontent() for output in outputs: - if data == output: + if data == output: data = "" if data is not "": count += 1 @@ -1111,8 +1111,8 @@ output_elements += "{:0>2x}".format(len(data)) for character in range(len(data)): output_elements += "{:0>2x}".format(ord(data[character])) - data = "" - + data = "" + # form eeprom data # category header eeprom.append("0a") @@ -1137,38 +1137,38 @@ eeprom.append("00") else: eeprom.append(element[0:2]) - element = element[2:len(element)] - # padding if length is odd bytes + element = element[2:len(element)] + # padding if length is odd bytes if padflag is True: eeprom.append("ff") - + return eeprom - + def ExtractEEPROMGeneralCategory(self, device): """ Extract "General" category data from slave ESI XML and generate EEPROM image data. @param device : 'device' object in the slave ESI XML @return eeprom : "Strings" category EEPROM image data - """ + """ eeprom = [] data = "" - + # category header eeprom.append("1e") eeprom.append("00") - + # category length eeprom.append("10") eeprom.append("00") - + # word 1 : Group Type index and Image index in STRINGS Category eeprom.append("{:0>2x}".format(self.GroupIdx)) eeprom.append("{:0>2x}".format(self.ImgIdx)) - + # word 2 : Device Type index and Device Name index in STRINGS Category eeprom.append("{:0>2x}".format(self.OrderIdx)) eeprom.append("{:0>2x}".format(self.NameIdx)) - + # word 3 : Physical Layer Port info. and CoE Details eeprom.append("01") # Physical Layer Port info - assume 01 # CoE Details; ----- @@ -1178,12 +1178,12 @@ if mb is not None : coe = mb.getCoE() if coe is not None: - for bit,flag in enumerate(["SdoInfo", "PdoAssign", "PdoConfig", + for bit,flag in enumerate(["SdoInfo", "PdoAssign", "PdoConfig", "PdoUpload", "CompleteAccess"]): if getattr(coe,"get%s"%flag)() is not None: - coe_details += 1<2x}".format(coe_details)) - + # word 4 : FoE Details and EoE Details # FoE Details; ----- if mb is not None and mb.getFoE() is not None: @@ -1195,7 +1195,7 @@ eeprom.append("01") else: eeprom.append("00") - + # word 5 : SoE Channels(reserved) and DS402 Channels # SoE Details; ----- if mb is not None and mb.getSoE() is not None: @@ -1209,10 +1209,10 @@ if coe is not None : ds402ch = coe.getDS402Channels() eeprom.append("01" if ds402ch in [True,1] else "00") - + # word 6 : SysmanClass(reserved) and Flags eeprom.append("00") # reserved - # Flags + # Flags en_safeop = False en_lrw = False if device.getType().getTcCfgModeSafeOp() == True \ @@ -1221,10 +1221,10 @@ if device.getType().getUseLrdLwr() == True \ or device.getType().getUseLrdLwr() == 1: en_lrw = True - + flags = "0b"+"000000"+str(int(en_lrw))+str(int(en_safeop)) eeprom.append("{:0>2x}".format(int(flags, 2))) - + # word 7 : Current On EBus (assume 0x0000) eeprom.append("00") eeprom.append("00") @@ -1247,20 +1247,20 @@ eeprom.append("00") eeprom.append("00") eeprom.append("00") - + return eeprom - + def ExtractEEPROMFMMUCategory(self, device): """ Extract "FMMU" category data from slave ESI XML and generate EEPROM image data. @param device : 'device' object in the slave ESI XML @return eeprom : "Strings" category EEPROM image data - """ + """ eeprom = [] data = "" count = 0 # number of FMMU padflag = False - + for fmmu in device.getFmmu(): count += 1 if fmmu.getcontent() == "Outputs": @@ -1269,7 +1269,7 @@ data += "02" if fmmu.getcontent() == "MBoxState": data += "03" - + # construct of EEPROM data if data is not "": # category header @@ -1280,7 +1280,7 @@ padflag = True eeprom.append("{:0>4x}".format((count+1)/2)[2:4]) eeprom.append("{:0>4x}".format((count+1)/2)[0:2]) - else: + else: eeprom.append("{:0>4x}".format((count)/2)[2:4]) eeprom.append("{:0>4x}".format((count)/2)[0:2]) for i in range(count): @@ -1289,22 +1289,22 @@ else: eeprom.append(data[0:2]) data = data[2:len(data)] - # padding if length is odd bytes + # padding if length is odd bytes if padflag is True: - eeprom.append("ff") - + eeprom.append("ff") + return eeprom - + def ExtractEEPROMSyncMCategory(self, device): """ Extract "SyncM" category data from slave ESI XML and generate EEPROM image data. @param device : 'device' object in the slave ESI XML @return eeprom : "Strings" category EEPROM image data - """ + """ eeprom = [] data = "" number = {"MBoxOut":"01", "MBoxIn":"02", "Outputs":"03", "Inputs":"04"} - + for sm in device.getSm(): for attr in [sm.getStartAddress(), sm.getDefaultSize(), @@ -1313,18 +1313,18 @@ data += "{:0>4x}".format(ExtractHexDecValue(attr))[2:4] data += "{:0>4x}".format(ExtractHexDecValue(attr))[0:2] else: - data += "0000" + data += "0000" if sm.getEnable() == "1" or sm.getEnable() == True: data += "01" else: data += "00" data += number[sm.getcontent()] - + if data is not "": # category header eeprom.append("29") eeprom.append("00") - # category length + # category length eeprom.append("{:0>4x}".format(len(data)/4)[2:4]) eeprom.append("{:0>4x}".format(len(data)/4)[0:2]) for i in range(len(data)/2): @@ -1335,21 +1335,21 @@ data = data[2:len(data)] return eeprom - + def ExtractEEPROMPDOCategory(self, device, pdotype): """ Extract ""PDO (Tx, Rx)"" category data from slave ESI XML and generate EEPROM image data. @param device : 'device' object in the slave ESI XML @param pdotype : identifier whether "TxPDO" or "RxPDO". @return eeprom : "Strings" category EEPROM image data - """ + """ eeprom = [] data = "" count = 0 en_fixed = False en_mandatory = False en_virtual = False - + for element in eval("device.get%s()"%pdotype): # PDO Index data += "{:0>4x}".format(ExtractHexDecValue(element.getIndex().getcontent()))[2:4] @@ -1384,7 +1384,7 @@ if element.getVirtual() == True or element.getVirtual(): en_virtual = True data += str(int(en_fixed)) + str(int(en_mandatory)) + str(int(en_virtual)) + "0" - + for entry in element.getEntry(): # Entry Index data += "{:0>4x}".format(ExtractHexDecValue(entry.getIndex().getcontent()))[2:4] @@ -1422,7 +1422,7 @@ if entry.getFixed() == True or entry.getFixed() == 1: en_fixed = True data += str(int(en_fixed)) + "000" - + if data is not "": # category header if pdotype == "TxPdo": @@ -1432,7 +1432,7 @@ else: eeprom.append("00") eeprom.append("00") - # category length + # category length eeprom.append("{:0>4x}".format(len(data)/4)[2:4]) eeprom.append("{:0>4x}".format(len(data)/4)[0:2]) data = str(data.lower()) @@ -1442,20 +1442,20 @@ else: eeprom.append(data[0:2]) data = data[2:len(data)] - + return eeprom - + def ExtractEEPROMDCCategory(self, device): """ Extract "DC(Distributed Clock)" category data from slave ESI XML and generate EEPROM image data. @param device : 'device' object in the slave ESI XML @return eeprom : "Strings" category EEPROM image data - """ + """ eeprom = [] data = "" count = 0 namecount = 0 - + if device.getDc() is not None: for element in device.getDc().getOpMode(): count += 1 @@ -1501,12 +1501,12 @@ # assume that word 11-12 are 0x0000 data += "0000" data += "0000" - + if data is not "": # category header eeprom.append("3c") eeprom.append("00") - # category length + # category length eeprom.append("{:0>4x}".format(len(data)/4)[2:4]) eeprom.append("{:0>4x}".format(len(data)/4)[0:2]) data = str(data.lower()) @@ -1516,9 +1516,9 @@ else: eeprom.append(data[0:2]) data = data[2:len(data)] - + return eeprom - + #------------------------------------------------------------------------------- # Used Register Access #------------------------------------------------------------------------------- @@ -1529,10 +1529,10 @@ @param offset : register address @param length : register length @return return_val : register data - """ + """ error, return_val = self.Controler.RemoteExec(REG_READ%(self.Controler.GetSlavePos(), offset, length), return_val = None) - return return_val - + return return_val + def RegWrite(self, address, data): """ Write data to slave ESC register using "ethercat reg_write -p %d %s %s" command. @@ -1540,28 +1540,28 @@ @param address : register address @param data : data to write @return return_val : the execution result of "ethercat reg_write" (for error check) - """ + """ error, return_val = self.Controler.RemoteExec(REG_WRITE%(self.Controler.GetSlavePos(), address, data), return_val = None) - return return_val - + return return_val + def Rescan(self): """ Synchronize EEPROM data in master controller with the data in slave device after EEPROM write. Command example : "ethercat rescan -p 0" - """ + """ error, return_val = self.Controler.RemoteExec(RESCAN%(self.Controler.GetSlavePos()), return_val = None) - + #------------------------------------------------------------------------------- # Common Use Methods #------------------------------------------------------------------------------- def CheckConnect(self, cyclic_flag): """ - Check connection status (1) between Beremiz and the master (2) between the master and the slave. + Check connection status (1) between Beremiz and the master (2) between the master and the slave. @param cyclic_flag: 0 - one shot, 1 - periodic @return True or False - """ + """ if self.Controler.GetCTRoot()._connector is not None: - # Check connection between the master and the slave. + # Check connection between the master and the slave. # Command example : "ethercat xml -p 0" error, return_val = self.Controler.RemoteExec(SLAVE_XML%(self.Controler.GetSlavePos()), return_val = None) number_of_lines = return_val.split("\n") @@ -1569,23 +1569,23 @@ if not cyclic_flag : self.CreateErrorDialog('No connected slaves') return False - + elif len(number_of_lines) > 2 : return True - else: + else: # The master controller is not connected to Beremiz host if not cyclic_flag : self.CreateErrorDialog('PLC not connected!') return False - + def CreateErrorDialog(self, mention): """ Create a dialog to indicate error or warning. @param mention : Error String - """ + """ app_frame = self.Controler.GetCTRoot().AppFrame - dlg = wx.MessageDialog (app_frame, mention, - ' Warning...', + dlg = wx.MessageDialog (app_frame, mention, + ' Warning...', wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() - dlg.Destroy() + dlg.Destroy() diff -r 9460872f1440 -r fec77f2b9e07 etherlab/ConfigEditor.py --- a/etherlab/ConfigEditor.py Fri Sep 28 17:15:53 2018 +0300 +++ b/etherlab/ConfigEditor.py Fri Sep 28 17:20:11 2018 +0300 @@ -67,22 +67,22 @@ LOCATION_MODEL = re.compile("(?:%[IQM](?:[XBWLD]?([0-9]+(?:\.[0-9]+)*)))$") class NodeVariablesSizer(wx.FlexGridSizer): - + def __init__(self, parent, controler, position_column=False): wx.FlexGridSizer.__init__(self, cols=1, hgap=0, rows=2, vgap=5) self.AddGrowableCol(0) self.AddGrowableRow(1) - + self.Controler = controler self.PositionColumn = position_column - + self.VariablesFilter = wx.ComboBox(parent, style=wx.TE_PROCESS_ENTER) self.VariablesFilter.Bind(wx.EVT_COMBOBOX, self.OnVariablesFilterChanged) self.VariablesFilter.Bind(wx.EVT_TEXT_ENTER, self.OnVariablesFilterChanged) self.VariablesFilter.Bind(wx.EVT_CHAR, self.OnVariablesFilterKeyDown) self.AddWindow(self.VariablesFilter, flag=wx.GROW) - - self.VariablesGrid = wx.gizmos.TreeListCtrl(parent, + + self.VariablesGrid = wx.gizmos.TreeListCtrl(parent, style=wx.TR_DEFAULT_STYLE | wx.TR_ROW_LINES | wx.TR_COLUMN_LINES | @@ -91,46 +91,46 @@ self.VariablesGrid.GetMainWindow().Bind(wx.EVT_LEFT_DOWN, self.OnVariablesGridLeftClick) self.AddWindow(self.VariablesGrid, flag=wx.GROW) - + self.Filters = [] for desc, value in VARIABLES_FILTERS: self.VariablesFilter.Append(desc) self.Filters.append(value) - + self.VariablesFilter.SetSelection(0) self.CurrentFilter = self.Filters[0] self.VariablesFilterFirstCharacter = True - + if position_column: for colname, colsize, colalign in zip(GetVariablesTableColnames(position_column), [40, 80, 350, 80, 100, 80, 150], - [wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT, - wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT, + [wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT, + wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]): self.VariablesGrid.AddColumn(_(colname), colsize, colalign) self.VariablesGrid.SetMainColumn(2) else: for colname, colsize, colalign in zip(GetVariablesTableColnames(), [40, 350, 80, 100, 80, 150], - [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_RIGHT, + [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]): self.VariablesGrid.AddColumn(_(colname), colsize, colalign) self.VariablesGrid.SetMainColumn(1) - + def RefreshView(self): entries = self.Controler.GetSlaveVariables(self.CurrentFilter) self.RefreshVariablesGrid(entries) - + def RefreshVariablesGrid(self, entries): root = self.VariablesGrid.GetRootItem() if not root.IsOk(): root = self.VariablesGrid.AddRoot(_("Slave entries")) self.GenerateVariablesGridBranch(root, entries, GetVariablesTableColnames(self.PositionColumn)) self.VariablesGrid.Expand(root) - + def GenerateVariablesGridBranch(self, root, entries, colnames, idx=0): item, root_cookie = self.VariablesGrid.GetFirstChild(root) - + no_more_items = not item.IsOk() for entry in entries: idx += 1 @@ -153,7 +153,7 @@ if not no_more_items: item, root_cookie = self.VariablesGrid.GetNextChild(root, root_cookie) no_more_items = not item.IsOk() - + if not no_more_items: to_delete = [] while item.IsOk(): @@ -161,9 +161,9 @@ item, root_cookie = self.VariablesGrid.GetNextChild(root, root_cookie) for item in to_delete: self.VariablesGrid.Delete(item) - + return idx - + def OnVariablesFilterChanged(self, event): filter = self.VariablesFilter.GetSelection() if filter != -1: @@ -190,29 +190,29 @@ self.VariablesFilter.SetValue(VARIABLE_INDEX_FILTER_FORMAT % self.CurrentFilter[0]) self.VariablesFilterFirstCharacter = True event.Skip() - + def OnVariablesFilterKeyDown(self, event): if self.VariablesFilterFirstCharacter: keycode = event.GetKeyCode() - if keycode not in [wx.WXK_RETURN, + if keycode not in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]: self.VariablesFilterFirstCharacter = False if keycode not in NAVIGATION_KEYS: self.VariablesFilter.SetValue("") - if keycode not in [wx.WXK_DELETE, - wx.WXK_NUMPAD_DELETE, + if keycode not in [wx.WXK_DELETE, + wx.WXK_NUMPAD_DELETE, wx.WXK_BACK]: event.Skip() else: event.Skip() - + def OnVariablesGridLeftClick(self, event): item, flags, col = self.VariablesGrid.HitTest(event.GetPosition()) if item.IsOk(): entry = self.VariablesGrid.GetItemPyData(item) data_type = entry.get("Type", "") data_size = self.Controler.GetSizeOfType(data_type) - + if col == -1 and data_size is not None: pdo_mapping = entry.get("PDOMapping", "") access = entry.get("Access", "") @@ -225,7 +225,7 @@ node_name = self.Controler.GetSlaveName(slave_pos) else: node_name = self.Controler.CTNName() - + if pdo_mapping != "": var_name = "%s_%4.4x_%2.2x" % (node_name, entry_index, entry_subindex) if pdo_mapping == "T": @@ -234,13 +234,13 @@ dir = "%Q" location = "%s%s" % (dir, data_size) + \ ".".join(map(lambda x:str(x), location + (entry_index, entry_subindex))) - + data = wx.TextDataObject(str((location, "location", data_type, var_name, "", access))) dragSource = wx.DropSource(self.VariablesGrid) dragSource.SetData(data) dragSource.DoDragDrop() return - + elif self.PositionColumn: location = self.Controler.GetCurrentLocation() +\ (slave_pos, entry_index, entry_subindex) @@ -249,51 +249,51 @@ dragSource.SetData(data) dragSource.DoDragDrop() return - + event.Skip() class NodeEditor(ConfTreeNodeEditor): - + CONFNODEEDITOR_TABS = [ (_("Ethercat node"), "_create_EthercatNodeEditor"), # Add Notebook Tab for EtherCAT Management Treebook (_("EtherCAT Management"), "_create_EtherCATManagementEditor") ] - + def _create_EthercatNodeEditor(self, prnt): self.EthercatNodeEditor = wx.Panel(prnt, style=wx.TAB_TRAVERSAL) - + main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5) main_sizer.AddGrowableCol(0) main_sizer.AddGrowableRow(1) - + variables_label = wx.StaticText(self.EthercatNodeEditor, label=_('Variable entries:')) main_sizer.AddWindow(variables_label, border=10, flag=wx.TOP|wx.LEFT|wx.RIGHT) - + self.NodeVariables = NodeVariablesSizer(self.EthercatNodeEditor, self.Controler) - main_sizer.AddSizer(self.NodeVariables, border=10, + main_sizer.AddSizer(self.NodeVariables, border=10, flag=wx.GROW|wx.BOTTOM|wx.LEFT|wx.RIGHT) - + self.EthercatNodeEditor.SetSizer(main_sizer) return self.EthercatNodeEditor - + def __init__(self, parent, controler, window): ConfTreeNodeEditor.__init__(self, parent, controler, window) - + # add Contoler for use EthercatSlave.py Method self.Controler = controler - + def GetBufferState(self): return False, False - + def RefreshView(self): ConfTreeNodeEditor.RefreshView(self) - + self.NodeVariables.RefreshView() - # -------------------For EtherCAT Management ---------------------------------------------- + # -------------------For EtherCAT Management ---------------------------------------------- def _create_EtherCATManagementEditor(self, prnt): self.EtherCATManagementEditor = wx.ScrolledWindow(prnt, style=wx.TAB_TRAVERSAL|wx.HSCROLL|wx.VSCROLL) @@ -302,14 +302,14 @@ self.EtherCATManagermentEditor_Main_Sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5) self.EtherCATManagermentEditor_Main_Sizer.AddGrowableCol(0) self.EtherCATManagermentEditor_Main_Sizer.AddGrowableRow(0) - + self.EtherCATManagementTreebook = EtherCATManagementTreebook(self.EtherCATManagementEditor, self.Controler, self) - + self.EtherCATManagermentEditor_Main_Sizer.AddSizer(self.EtherCATManagementTreebook, border=10, flag=wx.GROW) self.EtherCATManagementEditor.SetSizer(self.EtherCATManagermentEditor_Main_Sizer) return self.EtherCATManagementEditor - + def OnResize(self, event): self.EtherCATManagementEditor.GetBestSize() xstart, ystart = self.EtherCATManagementEditor.GetViewStart() @@ -318,7 +318,7 @@ posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT)) posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT)) self.EtherCATManagementEditor.Scroll(posx, posy) - self.EtherCATManagementEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, + self.EtherCATManagementEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy) event.Skip() # ------------------------------------------------------------------------------------------------------- @@ -328,13 +328,13 @@ def GetProcessVariablesTableColnames(): _ = lambda x : x - return ["#", _("Name"), - _("Read from (nodeid, index, subindex)"), + return ["#", _("Name"), + _("Read from (nodeid, index, subindex)"), _("Write to (nodeid, index, subindex)"), _("Description")] class ProcessVariablesTable(CustomTable): - + def GetValue(self, row, col): if row < self.GetNumberRows(): if col == 0: @@ -351,7 +351,7 @@ return value return "%d, #x%0.4X, #x%0.2X" % value return self.data[row].get(colname, "") - + def SetValue(self, row, col, value): if col < len(self.colnames): colname = self.GetColLabelValue(col, False) @@ -361,7 +361,7 @@ self.data[row]["WriteTo"] = value else: self.data[row][colname] = value - + def _updateColAttrs(self, grid): """ wx.grid.Grid -> update the column attributes to add the @@ -380,18 +380,18 @@ grid.SetReadOnly(row, col, False) else: grid.SetReadOnly(row, col, True) - + grid.SetCellEditor(row, col, editor) grid.SetCellRenderer(row, col, renderer) - + self.ResizeRow(grid, row) class ProcessVariableDropTarget(wx.TextDropTarget): - + def __init__(self, parent): wx.TextDropTarget.__init__(self) self.ParentWindow = parent - + def OnDropText(self, x, y, data): self.ParentWindow.Select() x, y = self.ParentWindow.ProcessVariablesGrid.CalcUnscrolledPosition(x, y) @@ -413,7 +413,7 @@ if result is not None: location = map(int, result.group(1).split('.')) master_location = self.ParentWindow.GetMasterLocation() - if (master_location == tuple(location[:len(master_location)]) and + if (master_location == tuple(location[:len(master_location)]) and len(location) - len(master_location) == 3): values = tuple(location[len(master_location):]) var_type = self.ParentWindow.Controler.GetSlaveVariableDataType(*values) @@ -436,10 +436,10 @@ message = _("'Read from' and 'Write to' variables types are not compatible") else: message = _("Invalid value \"%s\" for process variable")%data - + if message is not None: wx.CallAfter(self.ShowMessage, message) - + def ShowMessage(self, message): message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR) message.ShowModal() @@ -450,11 +450,11 @@ return [_("Position"), _("Index"), _("Subindex"), _("Value"), _("Description")] class StartupCommandDropTarget(wx.TextDropTarget): - + def __init__(self, parent): wx.TextDropTarget.__init__(self) self.ParentWindow = parent - + def OnDropText(self, x, y, data): self.ParentWindow.Select() message = None @@ -478,7 +478,7 @@ access = values[2] if location is not None: master_location = self.ParentWindow.GetMasterLocation() - if (master_location == tuple(location[:len(master_location)]) and + if (master_location == tuple(location[:len(master_location)]) and len(location) - len(master_location) == 3): if access in ["wo", "rw"]: self.ParentWindow.AddStartupCommand(*location[len(master_location):]) @@ -486,10 +486,10 @@ message = _("Entry can't be write through SDO") else: message = _("Invalid value \"%s\" for startup command")%data - + if message is not None: wx.CallAfter(self.ShowMessage, message) - + def ShowMessage(self, message): message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR) message.ShowModal() @@ -514,7 +514,7 @@ elif colname == "Subindex": return "#x%0.2X" % value return value - + def SetValue(self, row, col, value): if col < len(self.colnames): colname = self.GetColLabelValue(col, False) @@ -532,10 +532,10 @@ self.old_value = self.data[row][colname] value = int(value) self.data[row][colname] = value - + def GetOldValue(self): return self.old_value - + def _updateColAttrs(self, grid): """ wx.grid.Grid -> update the column attributes to add the @@ -554,13 +554,13 @@ else: editor = wx.grid.GridCellTextEditor() renderer = wx.grid.GridCellStringRenderer() - + grid.SetCellEditor(row, col, editor) grid.SetCellRenderer(row, col, renderer) grid.SetReadOnly(row, col, False) - + self.ResizeRow(grid, row) - + def GetCommandIndex(self, position, command_idx): for row, command in enumerate(self.data): if command["Position"] == position and command["command_idx"] == command_idx: @@ -568,15 +568,15 @@ return None class MasterNodesVariablesSizer(NodeVariablesSizer): - + def __init__(self, parent, controler): NodeVariablesSizer.__init__(self, parent, controler, True) - + self.CurrentNodesFilter = {} - + def SetCurrentNodesFilter(self, nodes_filter): self.CurrentNodesFilter = nodes_filter - + def RefreshView(self): if self.CurrentNodesFilter is not None: args = self.CurrentNodesFilter.copy() @@ -587,27 +587,27 @@ NODE_POSITION_FILTER_FORMAT = _("Node Position: %d") class MasterEditor(ConfTreeNodeEditor): - + CONFNODEEDITOR_TABS = [ (_("Network"), "_create_EthercatMasterEditor"), (_("Master State"), "_create_MasterStateEditor") ] - + def _create_MasterStateEditor(self, prnt): self.MasterStateEditor = wx.ScrolledWindow(prnt, style=wx.TAB_TRAVERSAL|wx.HSCROLL|wx.VSCROLL) self.MasterStateEditor.Bind(wx.EVT_SIZE, self.OnResize) - + self.MasterStateEditor_Panel_Main_Sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5) self.MasterStateEditor_Panel_Main_Sizer.AddGrowableCol(0) self.MasterStateEditor_Panel_Main_Sizer.AddGrowableRow(0) - + self.MasterStateEditor_Panel = MasterStatePanelClass(self.MasterStateEditor, self.Controler) - + self.MasterStateEditor_Panel_Main_Sizer.AddSizer(self.MasterStateEditor_Panel, border=10, flag=wx.GROW) - + self.MasterStateEditor.SetSizer(self.MasterStateEditor_Panel_Main_Sizer) return self.MasterStateEditor - + def OnResize(self, event): self.MasterStateEditor.GetBestSize() xstart, ystart = self.MasterStateEditor.GetViewStart() @@ -616,80 +616,80 @@ posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT)) posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT)) self.MasterStateEditor.Scroll(posx, posy) - self.MasterStateEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, + self.MasterStateEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy) event.Skip() - + def _create_EthercatMasterEditor(self, prnt): - self.EthercatMasterEditor = wx.ScrolledWindow(prnt, + self.EthercatMasterEditor = wx.ScrolledWindow(prnt, style=wx.TAB_TRAVERSAL|wx.HSCROLL|wx.VSCROLL) self.EthercatMasterEditor.Bind(wx.EVT_SIZE, self.OnResize) - + self.EthercatMasterEditorSizer = wx.BoxSizer(wx.VERTICAL) - + self.NodesFilter = wx.ComboBox(self.EthercatMasterEditor, style=wx.TE_PROCESS_ENTER) self.Bind(wx.EVT_COMBOBOX, self.OnNodesFilterChanged, self.NodesFilter) self.Bind(wx.EVT_TEXT_ENTER, self.OnNodesFilterChanged, self.NodesFilter) self.NodesFilter.Bind(wx.EVT_CHAR, self.OnNodesFilterKeyDown) - + process_variables_header = wx.BoxSizer(wx.HORIZONTAL) - + process_variables_label = wx.StaticText(self.EthercatMasterEditor, label=_("Process variables mapped between nodes:")) process_variables_header.AddWindow(process_variables_label, 1, flag=wx.ALIGN_CENTER_VERTICAL) - + for name, bitmap, help in [ ("AddVariableButton", "add_element", _("Add process variable")), ("DeleteVariableButton", "remove_element", _("Remove process variable")), ("UpVariableButton", "up", _("Move process variable up")), ("DownVariableButton", "down", _("Move process variable down"))]: - button = wx.lib.buttons.GenBitmapButton(self.EthercatMasterEditor, bitmap=GetBitmap(bitmap), + button = wx.lib.buttons.GenBitmapButton(self.EthercatMasterEditor, bitmap=GetBitmap(bitmap), size=wx.Size(28, 28), style=wx.NO_BORDER) button.SetToolTipString(help) setattr(self, name, button) process_variables_header.AddWindow(button, border=5, flag=wx.LEFT) - + self.ProcessVariablesGrid = CustomGrid(self.EthercatMasterEditor, style=wx.VSCROLL) self.ProcessVariablesGrid.SetMinSize(wx.Size(0, 150)) self.ProcessVariablesGrid.SetDropTarget(ProcessVariableDropTarget(self)) - self.ProcessVariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, + self.ProcessVariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnProcessVariablesGridCellChange) - self.ProcessVariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, + self.ProcessVariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnProcessVariablesGridCellLeftClick) self.ProcessVariablesGrid.Bind(wx.EVT_KEY_DOWN, self.OnProcessVariablesGridKeyDown) - + startup_commands_header = wx.BoxSizer(wx.HORIZONTAL) - + startup_commands_label = wx.StaticText(self.EthercatMasterEditor, label=_("Startup service variables assignments:")) startup_commands_header.AddWindow(startup_commands_label, 1, flag=wx.ALIGN_CENTER_VERTICAL) - + for name, bitmap, help in [ ("AddCommandButton", "add_element", _("Add startup service variable")), ("DeleteCommandButton", "remove_element", _("Remove startup service variable"))]: - button = wx.lib.buttons.GenBitmapButton(self.EthercatMasterEditor, bitmap=GetBitmap(bitmap), + button = wx.lib.buttons.GenBitmapButton(self.EthercatMasterEditor, bitmap=GetBitmap(bitmap), size=wx.Size(28, 28), style=wx.NO_BORDER) button.SetToolTipString(help) setattr(self, name, button) startup_commands_header.AddWindow(button, border=5, flag=wx.LEFT) - + self.StartupCommandsGrid = CustomGrid(self.EthercatMasterEditor, style=wx.VSCROLL) self.StartupCommandsGrid.SetDropTarget(StartupCommandDropTarget(self)) self.StartupCommandsGrid.SetMinSize(wx.Size(0, 150)) - self.StartupCommandsGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, + self.StartupCommandsGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnStartupCommandsGridCellChange) - self.StartupCommandsGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, + self.StartupCommandsGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, self.OnStartupCommandsGridEditorShow) - + self.NodesVariables = MasterNodesVariablesSizer(self.EthercatMasterEditor, self.Controler) - + main_staticbox = wx.StaticBox(self.EthercatMasterEditor, label=_("Node filter:")) staticbox_sizer = wx.StaticBoxSizer(main_staticbox, wx.VERTICAL) self.EthercatMasterEditorSizer.AddSizer(staticbox_sizer, 0, border=10, flag=wx.GROW|wx.ALL) - + main_staticbox_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=6, vgap=0) main_staticbox_sizer.AddGrowableCol(0) main_staticbox_sizer.AddGrowableRow(2) @@ -697,61 +697,61 @@ main_staticbox_sizer.AddGrowableRow(5) staticbox_sizer.AddSizer(main_staticbox_sizer, 1, flag=wx.GROW) main_staticbox_sizer.AddWindow(self.NodesFilter, border=5, flag=wx.GROW|wx.ALL) - main_staticbox_sizer.AddSizer(process_variables_header, border=5, + main_staticbox_sizer.AddSizer(process_variables_header, border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM) - main_staticbox_sizer.AddWindow(self.ProcessVariablesGrid, 1, + main_staticbox_sizer.AddWindow(self.ProcessVariablesGrid, 1, border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM) - main_staticbox_sizer.AddSizer(startup_commands_header, + main_staticbox_sizer.AddSizer(startup_commands_header, border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM) - main_staticbox_sizer.AddWindow(self.StartupCommandsGrid, 1, + main_staticbox_sizer.AddWindow(self.StartupCommandsGrid, 1, border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM) - + second_staticbox = wx.StaticBox(self.EthercatMasterEditor, label=_("Nodes variables filter:")) second_staticbox_sizer = wx.StaticBoxSizer(second_staticbox, wx.VERTICAL) second_staticbox_sizer.AddSizer(self.NodesVariables, 1, border=5, flag=wx.GROW|wx.ALL) - - main_staticbox_sizer.AddSizer(second_staticbox_sizer, 1, + + main_staticbox_sizer.AddSizer(second_staticbox_sizer, 1, border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM) - + self.EthercatMasterEditor.SetSizer(self.EthercatMasterEditorSizer) - + return self.EthercatMasterEditor def __init__(self, parent, controler, window): ConfTreeNodeEditor.__init__(self, parent, controler, window) - + # ------------------------------------------------------------------ self.Controler = controler # ------------------------------------------------------------------ - + self.ProcessVariables = [] self.CellShown = None self.NodesFilterFirstCharacter = True - + self.ProcessVariablesDefaultValue = {"Name": "", "ReadFrom": "", "WriteTo": "", "Description": ""} self.ProcessVariablesTable = ProcessVariablesTable(self, [], GetProcessVariablesTableColnames()) self.ProcessVariablesColSizes = [40, 100, 150, 150, 200] self.ProcessVariablesColAlignements = [wx.ALIGN_CENTER, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT] - + self.ProcessVariablesGrid.SetTable(self.ProcessVariablesTable) self.ProcessVariablesGrid.SetButtons({"Add": self.AddVariableButton, "Delete": self.DeleteVariableButton, "Up": self.UpVariableButton, "Down": self.DownVariableButton}) - + def _AddVariablesElement(new_row): self.ProcessVariablesTable.InsertRow(new_row, self.ProcessVariablesDefaultValue.copy()) self.SaveProcessVariables() self.ProcessVariablesTable.ResetView(self.ProcessVariablesGrid) return new_row setattr(self.ProcessVariablesGrid, "_AddRow", _AddVariablesElement) - + def _DeleteVariablesElement(row): self.ProcessVariablesTable.RemoveRow(row) self.SaveProcessVariables() self.ProcessVariablesTable.ResetView(self.ProcessVariablesGrid) setattr(self.ProcessVariablesGrid, "_DeleteRow", _DeleteVariablesElement) - + def _MoveVariablesElement(row, move): new_row = self.ProcessVariablesTable.MoveRow(row, move) if new_row != row: @@ -759,7 +759,7 @@ self.ProcessVariablesTable.ResetView(self.ProcessVariablesGrid) return new_row setattr(self.ProcessVariablesGrid, "_MoveRow", _MoveVariablesElement) - + _refresh_buttons = getattr(self.ProcessVariablesGrid, "RefreshButtons") def _RefreshButtons(): if self.NodesFilter.GetSelection() == 0: @@ -770,7 +770,7 @@ self.UpVariableButton.Enable(False) self.DownVariableButton.Enable(False) setattr(self.ProcessVariablesGrid, "RefreshButtons", _RefreshButtons) - + self.ProcessVariablesGrid.SetRowLabelSize(0) for col in range(self.ProcessVariablesTable.GetNumberCols()): attr = wx.grid.GridCellAttr() @@ -779,16 +779,16 @@ self.ProcessVariablesGrid.SetColMinimalWidth(col, self.ProcessVariablesColSizes[col]) self.ProcessVariablesGrid.AutoSizeColumn(col, False) self.ProcessVariablesGrid.RefreshButtons() - + self.StartupCommandsDefaultValue = {"Position": 0, "Index": 0, "Subindex": 0, "Value": 0, "Description": ""} self.StartupCommandsTable = StartupCommandsTable(self, [], GetStartupCommandsTableColnames()) self.StartupCommandsColSizes = [100, 100, 50, 100, 200] self.StartupCommandsColAlignements = [wx.ALIGN_CENTER, wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT] - + self.StartupCommandsGrid.SetTable(self.StartupCommandsTable) self.StartupCommandsGrid.SetButtons({"Add": self.AddCommandButton, "Delete": self.DeleteCommandButton}) - + def _AddCommandsElement(new_row): command = self.StartupCommandsDefaultValue.copy() command_idx = self.Controler.AppendStartupCommand(command) @@ -796,14 +796,14 @@ self.RefreshBuffer() return self.StartupCommandsTable.GetCommandIndex(command["Position"], command_idx) setattr(self.StartupCommandsGrid, "_AddRow", _AddCommandsElement) - + def _DeleteCommandsElement(row): command = self.StartupCommandsTable.GetRow(row) self.Controler.RemoveStartupCommand(command["Position"], command["command_idx"]) self.RefreshStartupCommands() self.RefreshBuffer() setattr(self.StartupCommandsGrid, "_DeleteRow", _DeleteCommandsElement) - + self.StartupCommandsGrid.SetRowLabelSize(0) for col in range(self.StartupCommandsTable.GetNumberCols()): attr = wx.grid.GridCellAttr() @@ -812,32 +812,32 @@ self.StartupCommandsGrid.SetColMinimalWidth(col, self.StartupCommandsColSizes[col]) self.StartupCommandsGrid.AutoSizeColumn(col, False) self.StartupCommandsGrid.RefreshButtons() - + def RefreshBuffer(self): self.ParentWindow.RefreshTitle() self.ParentWindow.RefreshFileMenu() self.ParentWindow.RefreshEditMenu() self.ParentWindow.RefreshPageTitles() - + def GetBufferState(self): return self.Controler.GetBufferState() - + def Undo(self): self.Controler.LoadPrevious() self.RefreshView() - + def Redo(self): self.Controler.LoadNext() self.RefreshView() - + def RefreshView(self): ConfTreeNodeEditor.RefreshView(self) - + self.RefreshNodesFilter() self.RefreshProcessVariables() self.RefreshStartupCommands() self.NodesVariables.RefreshView() - + def RefreshNodesFilter(self): value = self.NodesFilter.GetValue() self.NodesFilter.Clear() @@ -857,7 +857,7 @@ except Exception: self.NodesFilter.SetSelection(0) self.RefreshCurrentNodesFilter() - + def RefreshCurrentNodesFilter(self): filter = self.NodesFilter.GetSelection() if filter != -1: @@ -879,7 +879,7 @@ self.NodesFilter.SetValue(NODE_POSITION_FILTER_FORMAT % self.CurrentNodesFilter["slave_pos"]) self.NodesFilterFirstCharacter = True self.NodesVariables.SetCurrentNodesFilter(self.CurrentNodesFilter) - + def RefreshProcessVariables(self): if self.CurrentNodesFilter is not None: self.ProcessVariables = self.Controler.GetProcessVariables() @@ -892,7 +892,7 @@ self.ProcessVariablesTable.SetData(data) self.ProcessVariablesTable.ResetView(self.ProcessVariablesGrid) self.ProcessVariablesGrid.RefreshButtons() - + def SaveProcessVariables(self): if self.CurrentNodesFilter is not None: if len(self.CurrentNodesFilter) > 0: @@ -900,7 +900,7 @@ else: self.Controler.SetProcessVariables(self.ProcessVariablesTable.GetData()) self.RefreshBuffer() - + def RefreshStartupCommands(self, position=None, command_idx=None): if self.CurrentNodesFilter is not None: col = max(self.StartupCommandsGrid.GetGridCursorCol(), 0) @@ -909,15 +909,15 @@ self.StartupCommandsTable.ResetView(self.StartupCommandsGrid) if position is not None and command_idx is not None: self.SelectStartupCommand(position, command_idx, col) - + def SelectStartupCommand(self, position, command_idx, col): self.StartupCommandsGrid.SetSelectedCell( self.StartupCommandsTable.GetCommandIndex(position, command_idx), col) - + def GetMasterLocation(self): return self.Controler.GetCurrentLocation() - + def AddStartupCommand(self, position, index, subindex): col = max(self.StartupCommandsGrid.GetGridCursorCol(), 0) command = self.StartupCommandsDefaultValue.copy() @@ -928,7 +928,7 @@ self.RefreshStartupCommands() self.RefreshBuffer() self.SelectStartupCommand(position, command_idx, col) - + def OnNodesFilterChanged(self, event): self.RefreshCurrentNodesFilter() if self.CurrentNodesFilter is not None: @@ -936,22 +936,22 @@ self.RefreshStartupCommands() self.NodesVariables.RefreshView() event.Skip() - + def OnNodesFilterKeyDown(self, event): if self.NodesFilterFirstCharacter: keycode = event.GetKeyCode() - if keycode not in [wx.WXK_RETURN, + if keycode not in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]: self.NodesFilterFirstCharacter = False if keycode not in NAVIGATION_KEYS: self.NodesFilter.SetValue("") - if keycode not in [wx.WXK_DELETE, - wx.WXK_NUMPAD_DELETE, + if keycode not in [wx.WXK_DELETE, + wx.WXK_NUMPAD_DELETE, wx.WXK_BACK]: event.Skip() else: event.Skip() - + def OnProcessVariablesGridCellChange(self, event): row, col = event.GetRow(), event.GetCol() colname = self.ProcessVariablesTable.GetColLabelValue(col, False) @@ -973,7 +973,7 @@ dialog.ShowModal() dialog.Destroy() event.Veto() - + def OnProcessVariablesGridCellLeftClick(self, event): row = event.GetRow() if event.GetCol() == 0: @@ -984,30 +984,30 @@ number = self.ProcessVariablesTable.GetValueByName(row, "Number") location = "%%M%s" % data_size + \ ".".join(map(lambda x:str(x), self.Controler.GetCurrentLocation() + (number,))) - + data = wx.TextDataObject(str((location, "location", var_type, var_name, ""))) dragSource = wx.DropSource(self.ProcessVariablesGrid) dragSource.SetData(data) dragSource.DoDragDrop() event.Skip() - + def OnProcessVariablesGridKeyDown(self, event): keycode = event.GetKeyCode() col = self.ProcessVariablesGrid.GetGridCursorCol() row = self.ProcessVariablesGrid.GetGridCursorRow() colname = self.ProcessVariablesTable.GetColLabelValue(col, False) - if (keycode in (wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE) and + if (keycode in (wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE) and (colname.startswith("Read from") or colname.startswith("Write to"))): self.ProcessVariablesTable.SetValue(row, col, "") self.SaveProcessVariables() wx.CallAfter(self.ProcessVariablesTable.ResetView, self.ProcessVariablesGrid) else: event.Skip() - + def OnStartupCommandsGridEditorShow(self, event): self.CellShown = event.GetRow(), event.GetCol() event.Skip() - + def OnStartupCommandsGridCellChange(self, event): row, col = event.GetRow(), event.GetCol() if self.CellShown == (row, col): @@ -1029,7 +1029,7 @@ else: command = self.StartupCommandsTable.GetRow(row) self.Controler.SetStartupCommandInfos(command) - if colname in ["Index", "SubIndex"]: + if colname in ["Index", "SubIndex"]: wx.CallAfter(self.RefreshStartupCommands, command["Position"], command["command_idx"]) if message is None: self.RefreshBuffer() @@ -1041,7 +1041,7 @@ event.Veto() else: event.Veto() - + def OnResize(self, event): self.EthercatMasterEditor.GetBestSize() xstart, ystart = self.EthercatMasterEditor.GetViewStart() @@ -1050,10 +1050,10 @@ posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT)) posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT)) self.EthercatMasterEditor.Scroll(posx, posy) - self.EthercatMasterEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, + self.EthercatMasterEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy) event.Skip() - + #def OnButtonClick(self, event): # self.MasterState = self.Controler.getMasterState() # if self.MasterState: @@ -1067,7 +1067,7 @@ # self.TxByte.SetValue(self.MasterState["TXbyte"]) # self.TxError.SetValue(self.MasterState["TXerror"]) # self.LostFrames.SetValue(self.MasterState["lost"]) - + # self.TxFrameRate1.SetValue(self.MasterState["TXframerate1"]) # self.TxFrameRate2.SetValue(self.MasterState["TXframerate2"]) # self.TxFrameRate3.SetValue(self.MasterState["TXframerate3"]) @@ -1080,41 +1080,41 @@ # self.FrameLoss1.SetValue(self.MasterState["frameloss1"]) # self.FrameLoss2.SetValue(self.MasterState["frameloss2"]) # self.FrameLoss3.SetValue(self.MasterState["frameloss3"]) - + class LibraryEditorSizer(wx.FlexGridSizer): - + def __init__(self, parent, module_library, buttons): wx.FlexGridSizer.__init__(self, cols=1, hgap=0, rows=4, vgap=5) - + self.ModuleLibrary = module_library self.ParentWindow = parent - + self.AddGrowableCol(0) self.AddGrowableRow(1) self.AddGrowableRow(3) - - ESI_files_label = wx.StaticText(parent, + + ESI_files_label = wx.StaticText(parent, label=_("ESI Files:")) - self.AddWindow(ESI_files_label, border=10, + self.AddWindow(ESI_files_label, border=10, flag=wx.TOP|wx.LEFT|wx.RIGHT) - + folder_tree_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=1, vgap=0) folder_tree_sizer.AddGrowableCol(0) folder_tree_sizer.AddGrowableRow(0) - self.AddSizer(folder_tree_sizer, border=10, + self.AddSizer(folder_tree_sizer, border=10, flag=wx.GROW|wx.LEFT|wx.RIGHT) - + self.ESIFiles = FolderTree(parent, self.GetPath(), editable=False) self.ESIFiles.SetFilter(".xml") folder_tree_sizer.AddWindow(self.ESIFiles, flag=wx.GROW) - + buttons_sizer = wx.BoxSizer(wx.VERTICAL) - folder_tree_sizer.AddSizer(buttons_sizer, + folder_tree_sizer.AddSizer(buttons_sizer, flag=wx.ALIGN_CENTER_VERTICAL) - + for idx, (name, bitmap, help, callback) in enumerate(buttons): - button = wx.lib.buttons.GenBitmapButton(parent, - bitmap=GetBitmap(bitmap), + button = wx.lib.buttons.GenBitmapButton(parent, + bitmap=GetBitmap(bitmap), size=wx.Size(28, 28), style=wx.NO_BORDER) button.SetToolTipString(help) setattr(self, name, button) @@ -1127,12 +1127,12 @@ if callback is not None: parent.Bind(wx.EVT_BUTTON, callback, button) buttons_sizer.AddWindow(button, border=10, flag=flag) - - modules_label = wx.StaticText(parent, + + modules_label = wx.StaticText(parent, label=_("Modules library:")) - self.AddSizer(modules_label, border=10, + self.AddSizer(modules_label, border=10, flag=wx.LEFT|wx.RIGHT) - + self.ModulesGrid = wx.gizmos.TreeListCtrl(parent, style=wx.TR_DEFAULT_STYLE | wx.TR_ROW_LINES | @@ -1145,51 +1145,51 @@ self.OnModulesGridBeginLabelEdit) self.ModulesGrid.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnModulesGridEndLabelEdit) - self.ModulesGrid.GetHeaderWindow().Bind(wx.EVT_MOTION, + self.ModulesGrid.GetHeaderWindow().Bind(wx.EVT_MOTION, self.OnModulesGridHeaderMotion) - self.AddWindow(self.ModulesGrid, border=10, + self.AddWindow(self.ModulesGrid, border=10, flag=wx.GROW|wx.BOTTOM|wx.LEFT|wx.RIGHT) - + for colname, colsize, colalign in zip( - [_("Name")] + [param_infos["column_label"] - for param, param_infos in + [_("Name")] + [param_infos["column_label"] + for param, param_infos in self.ModuleLibrary.MODULES_EXTRA_PARAMS], - [400] + [param_infos["column_size"] - for param, param_infos in + [400] + [param_infos["column_size"] + for param, param_infos in self.ModuleLibrary.MODULES_EXTRA_PARAMS], [wx.ALIGN_LEFT] + [wx.ALIGN_RIGHT] * len(self.ModuleLibrary.MODULES_EXTRA_PARAMS)): self.ModulesGrid.AddColumn(_(colname), colsize, colalign, edit=True) self.ModulesGrid.SetMainColumn(0) - + self.CurrentSelectedCol = None self.LastToolTipCol = None - + def GetPath(self): return self.ModuleLibrary.GetPath() - + def SetControlMinSize(self, size): self.ESIFiles.SetMinSize(size) self.ModulesGrid.SetMinSize(size) - + def GetSelectedFilePath(self): return self.ESIFiles.GetPath() - + def RefreshView(self): self.ESIFiles.RefreshTree() self.RefreshModulesGrid() - + def RefreshModulesGrid(self): root = self.ModulesGrid.GetRootItem() if not root.IsOk(): root = self.ModulesGrid.AddRoot("Modules") - self.GenerateModulesGridBranch(root, - self.ModuleLibrary.GetModulesLibrary(), + self.GenerateModulesGridBranch(root, + self.ModuleLibrary.GetModulesLibrary(), GetVariablesTableColnames()) self.ModulesGrid.Expand(root) - + def GenerateModulesGridBranch(self, root, modules, colnames): item, root_cookie = self.ModulesGrid.GetFirstChild(root) - + no_more_items = not item.IsOk() for module in modules: if no_more_items: @@ -1197,8 +1197,8 @@ self.ModulesGrid.SetItemText(item, module["name"], 0) if module["infos"] is not None: for param_idx, (param, param_infos) in enumerate(self.ModuleLibrary.MODULES_EXTRA_PARAMS): - self.ModulesGrid.SetItemText(item, - str(module["infos"][param]), + self.ModulesGrid.SetItemText(item, + str(module["infos"][param]), param_idx + 1) else: self.ModulesGrid.SetItemBackgroundColour(item, wx.LIGHT_GREY) @@ -1207,7 +1207,7 @@ if not no_more_items: item, root_cookie = self.ModulesGrid.GetNextChild(root, root_cookie) no_more_items = not item.IsOk() - + if not no_more_items: to_delete = [] while item.IsOk(): @@ -1215,44 +1215,44 @@ item, root_cookie = self.ModulesGrid.GetNextChild(root, root_cookie) for item in to_delete: self.ModulesGrid.Delete(item) - + def OnImportButton(self, event): dialog = wx.FileDialog(self.ParentWindow, - _("Choose an XML file"), - os.getcwd(), "", + _("Choose an XML file"), + os.getcwd(), "", _("XML files (*.xml)|*.xml|All files|*.*"), wx.OPEN) - + if dialog.ShowModal() == wx.ID_OK: filepath = dialog.GetPath() if self.ModuleLibrary.ImportModuleLibrary(filepath): wx.CallAfter(self.RefreshView) else: - message = wx.MessageDialog(self, - _("No such XML file: %s\n") % filepath, + message = wx.MessageDialog(self, + _("No such XML file: %s\n") % filepath, _("Error"), wx.OK|wx.ICON_ERROR) message.ShowModal() message.Destroy() dialog.Destroy() - + event.Skip() - + def OnDeleteButton(self, event): filepath = self.GetSelectedFilePath() if os.path.isfile(filepath): folder, filename = os.path.split(filepath) - - dialog = wx.MessageDialog(self.ParentWindow, - _("Do you really want to delete the file '%s'?") % filename, + + dialog = wx.MessageDialog(self.ParentWindow, + _("Do you really want to delete the file '%s'?") % filename, _("Delete File"), wx.YES_NO|wx.ICON_QUESTION) remove = dialog.ShowModal() == wx.ID_YES dialog.Destroy() - + if remove: os.remove(filepath) self.ModuleLibrary.LoadModules() wx.CallAfter(self.RefreshView) event.Skip() - + def OnModulesGridLeftDown(self, event): item, flags, col = self.ModulesGrid.HitTest(event.GetPosition()) if item.IsOk(): @@ -1293,8 +1293,8 @@ wx.CallAfter(self.RefreshModulesGrid) event.Skip() except ValueError: - message = wx.MessageDialog(self, - _("Module %s must be an integer!") % stripped_column_label, + message = wx.MessageDialog(self, + _("Module %s must be an integer!") % stripped_column_label, _("Error"), wx.OK|wx.ICON_ERROR) message.ShowModal() message.Destroy() @@ -1303,7 +1303,7 @@ event.Veto() else: event.Veto() - + def OnModulesGridHeaderMotion(self, event): item, flags, col = self.ModulesGrid.HitTest(event.GetPosition()) if col != self.LastToolTipCol and self.LastToolTipCol is not None: @@ -1312,51 +1312,51 @@ if col > 0 and self.LastToolTipCol != col: self.LastToolTipCol = col param, param_infos = self.ModuleLibrary.MODULES_EXTRA_PARAMS[col - 1] - wx.CallAfter(self.ModulesGrid.GetHeaderWindow().SetToolTipString, + wx.CallAfter(self.ModulesGrid.GetHeaderWindow().SetToolTipString, param_infos["description"]) event.Skip() class DatabaseManagementDialog(wx.Dialog): - + def __init__(self, parent, database): wx.Dialog.__init__(self, parent, size=wx.Size(700, 500), title=_('ESI Files Database management'), style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER) - + main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10) main_sizer.AddGrowableCol(0) main_sizer.AddGrowableRow(0) - + self.DatabaseSizer = LibraryEditorSizer(self, database, [("ImportButton", "ImportESI", _("Import file to ESI files database"), None), ("DeleteButton", "remove_element", _("Remove file from database"), None)]) self.DatabaseSizer.SetControlMinSize(wx.Size(0, 0)) main_sizer.AddSizer(self.DatabaseSizer, border=10, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT) - + button_sizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE) button_sizer.GetAffirmativeButton().SetLabel(_("Add file to project")) button_sizer.GetCancelButton().SetLabel(_("Close")) - main_sizer.AddSizer(button_sizer, border=10, + main_sizer.AddSizer(button_sizer, border=10, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT) - + self.SetSizer(main_sizer) - + self.DatabaseSizer.RefreshView() - + def GetValue(self): return self.DatabaseSizer.GetSelectedFilePath() class LibraryEditor(ConfTreeNodeEditor): - + CONFNODEEDITOR_TABS = [ (_("Modules Library"), "_create_ModuleLibraryEditor")] - + def _create_ModuleLibraryEditor(self, prnt): self.ModuleLibraryEditor = wx.ScrolledWindow(prnt, style=wx.TAB_TRAVERSAL|wx.HSCROLL|wx.VSCROLL) self.ModuleLibraryEditor.Bind(wx.EVT_SIZE, self.OnResize) - + self.ModuleLibrarySizer = LibraryEditorSizer(self.ModuleLibraryEditor, self.Controler.GetModulesLibraryInstance(), [("ImportButton", "ImportESI", _("Import ESI file"), None), @@ -1364,30 +1364,30 @@ ("DeleteButton", "remove_element", _("Remove file from library"), None)]) self.ModuleLibrarySizer.SetControlMinSize(wx.Size(0, 200)) self.ModuleLibraryEditor.SetSizer(self.ModuleLibrarySizer) - + return self.ModuleLibraryEditor def __init__(self, parent, controler, window): ConfTreeNodeEditor.__init__(self, parent, controler, window) - + self.RefreshView() - + def RefreshView(self): ConfTreeNodeEditor.RefreshView(self) self.ModuleLibrarySizer.RefreshView() def OnAddButton(self, event): - dialog = DatabaseManagementDialog(self, + dialog = DatabaseManagementDialog(self, self.Controler.GetModulesDatabaseInstance()) - + if dialog.ShowModal() == wx.ID_OK: module_library = self.Controler.GetModulesLibraryInstance() module_library.ImportModuleLibrary(dialog.GetValue()) - + dialog.Destroy() - + wx.CallAfter(self.ModuleLibrarySizer.RefreshView) - + event.Skip() def OnResize(self, event): @@ -1398,7 +1398,6 @@ posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT)) posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT)) self.ModuleLibraryEditor.Scroll(posx, posy) - self.ModuleLibraryEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, + self.ModuleLibraryEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy) event.Skip() - diff -r 9460872f1440 -r fec77f2b9e07 etherlab/EtherCATManagementEditor.py --- a/etherlab/EtherCATManagementEditor.py Fri Sep 28 17:15:53 2018 +0300 +++ b/etherlab/EtherCATManagementEditor.py Fri Sep 28 17:20:11 2018 +0300 @@ -23,7 +23,7 @@ import wx.grid as gridlib #------------------------------------------------------------- -# ------------ for register management --------------- +# ------------ for register management --------------- from xml.dom import minidom #------------------------------------------------------------- @@ -39,7 +39,7 @@ # Sync Managers Table #------------------------------------------------------------------------------- class SyncManagersTable(CustomTable): - def GetValue(self, row, col): + def GetValue(self, row, col): if row < self.GetNumberRows(): if col == 0: return row @@ -60,15 +60,15 @@ self.parent = parent self.Controler = controler self.NodeEditor = node_editor - + self.EtherCATManagementClassObject = {} - + # fill EtherCAT Management Treebook for pname, pclass, subs in [ ("Slave State", SlaveStatePanelClass, []), ("SDO Management", SDOPanelClass, []), ("PDO Monitoring", PDOPanelClass, []), - ("ESC Management", EEPROMAccessPanel, [ + ("ESC Management", EEPROMAccessPanel, [ ("Smart View", SlaveSiiSmartView), ("Hex View", HexView)]), ("Register Access", RegisterAccessPanel, [])]: @@ -78,22 +78,22 @@ self.Bind(wx.EVT_TREEBOOK_PAGE_CHANGED, self.OnPageChanged) self.Bind(wx.EVT_TREEBOOK_PAGE_CHANGING, self.OnPageChanging) - + def OnPageChanged(self, event): old = event.GetOldSelection() new = event.GetSelection() sel = event.GetSelection() event.Skip() - + def OnPageChanging(self, event): old = event.GetOldSelection() new = event.GetSelection() sel = event.GetSelection() - event.Skip() - + event.Skip() + #------------------------------------------------------------------------------- # For SlaveState Panel -#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- class SlaveStatePanelClass(wx.Panel): def __init__(self, parent, controler): """ @@ -104,13 +104,13 @@ wx.Panel.__init__(self, parent, -1, (0, 0), size=wx.DefaultSize, style = wx.SUNKEN_BORDER) self.Controler = controler self.parent = parent - + # initialize SlaveStatePanel UI dictionaries self.StaticBoxDic = {} self.StaticTextDic = {} self.TextCtrlDic = {} self.ButtonDic = {} - + # iniitalize BoxSizer and FlexGridSizer self.SizerDic = { "SlaveState_main_sizer" : wx.BoxSizer(wx.VERTICAL), @@ -120,15 +120,15 @@ "SlaveState_sizer" : wx.FlexGridSizer(cols=1, hgap=10, rows=2, vgap=10), "SlaveState_up_sizer" : wx.FlexGridSizer(cols=4, hgap=10, rows=2, vgap=10), "SlaveState_down_sizer" : wx.FlexGridSizer(cols=2, hgap=10, rows=1, vgap=10)} - + # initialize StaticBox and StaticBoxSizer for box_name, box_label in [ ("SlaveInfosDetailsBox", "Slave Informations"), ("SyncManagerBox", "Sync Manager"), ("SlaveStateBox", "Slave State Transition && Monitoring")]: self.StaticBoxDic[box_name] = wx.StaticBox(self, label=_(box_label)) - self.SizerDic[box_name] = wx.StaticBoxSizer(self.StaticBoxDic[box_name]) - + self.SizerDic[box_name] = wx.StaticBoxSizer(self.StaticBoxDic[box_name]) + for statictext_name, statictext_label, textctrl_name in [ ("VendorLabel", "Vendor:", "vendor"), ("ProductcodeLabel", "Product code:", "product_code"), @@ -136,16 +136,16 @@ ("PhysicsLabel", "Physics:", "physics")]: self.StaticTextDic[statictext_name] = wx.StaticText(self, label=_(statictext_label)) self.TextCtrlDic[textctrl_name] = wx.TextCtrl(self, size=wx.Size(130, 24), style=wx.TE_READONLY) - self.SizerDic["SlaveInfosDetailsInnerSizer"].AddMany([self.StaticTextDic[statictext_name], - self.TextCtrlDic[textctrl_name]]) - + self.SizerDic["SlaveInfosDetailsInnerSizer"].AddMany([self.StaticTextDic[statictext_name], + self.TextCtrlDic[textctrl_name]]) + self.SizerDic["SlaveInfosDetailsBox"].AddSizer(self.SizerDic["SlaveInfosDetailsInnerSizer"]) - - self.SyncManagersGrid = CustomGrid(self, size=wx.Size(605,155), style=wx.VSCROLL) - - self.SizerDic["SyncManagerInnerSizer"].Add(self.SyncManagersGrid) + + self.SyncManagersGrid = CustomGrid(self, size=wx.Size(605,155), style=wx.VSCROLL) + + self.SizerDic["SyncManagerInnerSizer"].Add(self.SyncManagersGrid) self.SizerDic["SyncManagerBox"].Add(self.SizerDic["SyncManagerInnerSizer"]) - + for button_name, button_id, button_label, button_tooltipstring, event_method, sub_item in [ ("InitButton", 0, "INIT", "State Transition to \"Init\" State", self.OnButtonClick, []), ("PreOPButton", 1, "PREOP", "State Transition to \"PreOP\" State", self.OnButtonClick, [ @@ -160,46 +160,46 @@ for statictext_name, statictext_label, textctrl_name in sub_item : self.StaticTextDic[statictext_name] = wx.StaticText(self, label=_(statictext_label)) self.TextCtrlDic[textctrl_name] = wx.TextCtrl(self, size=wx.DefaultSize, style=wx.TE_READONLY) - self.SizerDic["SlaveState_up_sizer"].AddMany([self.StaticTextDic[statictext_name], + self.SizerDic["SlaveState_up_sizer"].AddMany([self.StaticTextDic[statictext_name], self.TextCtrlDic[textctrl_name]]) - + for button_name, button_label, button_tooltipstring, event_method in [ ("StartTimerButton", "Start State Monitoring", "Slave State Update Restart", self.StartTimer), ("StopTimerButton", "Stop State Monitoring", "Slave State Update Stop", self.CurrentStateThreadStop)]: self.ButtonDic[button_name] = wx.Button(self, label=_(button_label)) self.ButtonDic[button_name].Bind(wx.EVT_BUTTON, event_method) self.ButtonDic[button_name].SetToolTipString(button_tooltipstring) - self.SizerDic["SlaveState_down_sizer"].Add(self.ButtonDic[button_name]) - - self.SizerDic["SlaveState_sizer"].AddMany([self.SizerDic["SlaveState_up_sizer"], + self.SizerDic["SlaveState_down_sizer"].Add(self.ButtonDic[button_name]) + + self.SizerDic["SlaveState_sizer"].AddMany([self.SizerDic["SlaveState_up_sizer"], self.SizerDic["SlaveState_down_sizer"]]) - + self.SizerDic["SlaveStateBox"].Add(self.SizerDic["SlaveState_sizer"]) - + self.SizerDic["SlaveState_inner_main_sizer"].AddMany([ self.SizerDic["SlaveInfosDetailsBox"], self.SizerDic["SyncManagerBox"], self.SizerDic["SlaveStateBox"]]) - + self.SizerDic["SlaveState_main_sizer"].Add(self.SizerDic["SlaveState_inner_main_sizer"]) - + self.SetSizer(self.SizerDic["SlaveState_main_sizer"]) - + # register a timer for periodic exectuion of slave state update (period: 1000 ms) self.Bind(wx.EVT_TIMER, self.GetCurrentState) - + self.CreateSyncManagerTable() - + self.Centre() - + def CreateSyncManagerTable(self): """ Create grid for "SyncManager" """ - # declare Table object + # declare Table object self.SyncManagersTable = SyncManagersTable(self, [], GetSyncManagersTableColnames()) self.SyncManagersGrid.SetTable(self.SyncManagersTable) # set grid alignment attr. (CENTER) - self.SyncManagersGridColAlignements = [wx.ALIGN_CENTRE, wx.ALIGN_CENTRE, wx.ALIGN_CENTRE, + self.SyncManagersGridColAlignements = [wx.ALIGN_CENTRE, wx.ALIGN_CENTRE, wx.ALIGN_CENTRE, wx.ALIGN_CENTRE, wx.ALIGN_CENTRE, wx.ALIGN_CENTRE] # set grid size self.SyncManagersGridColSizes = [40, 150, 100, 100, 100, 100] @@ -209,10 +209,10 @@ attr.SetAlignment(self.SyncManagersGridColAlignements[col], wx.ALIGN_CENTRE) self.SyncManagersGrid.SetColAttr(col, attr) self.SyncManagersGrid.SetColMinimalWidth(col, self.SyncManagersGridColSizes[col]) - self.SyncManagersGrid.AutoSizeColumn(col, False) - + self.SyncManagersGrid.AutoSizeColumn(col, False) + self.RefreshSlaveInfos() - + def RefreshSlaveInfos(self): """ Fill data in "Slave Information" and "SyncManager" @@ -220,7 +220,7 @@ slave_infos = self.Controler.GetSlaveInfos() sync_manager_section = ["vendor", "product_code", "revision_number", "physics"] if slave_infos is not None: - # this method is same as "TextCtrl.SetValue" + # this method is same as "TextCtrl.SetValue" for textctrl_name in sync_manager_section: self.TextCtrlDic[textctrl_name].SetValue(slave_infos[textctrl_name]) self.SyncManagersTable.SetData(slave_infos["sync_managers"]) @@ -230,7 +230,7 @@ self.TextCtrlDic[textctrl_name].SetValue("") self.SyncManagersTable.SetData([]) self.SyncManagersTable.ResetView(self.SyncManagersGrid) - + def OnButtonClick(self, event): """ Event handler for slave state transition button click (Init, PreOP, SafeOP, OP button) @@ -239,7 +239,7 @@ check_connect_flag = self.Controler.CommonMethod.CheckConnect(False) if check_connect_flag : state_dic = ["INIT", "PREOP", "SAFEOP", "OP"] - + # If target state is one of {INIT, PREOP, SAFEOP}, request slave state transition immediately. if event.GetId() < 3 : self.Controler.CommonMethod.RequestSlaveState(state_dic[event.GetId()]) @@ -254,8 +254,8 @@ self.Controler.CommonMethod.RequestSlaveState("OP") self.TextCtrlDic["TargetState"].SetValue("OP") else : - self.Controler.CommonMethod.CreateErrorDialog("PLC is Not Started") - + self.Controler.CommonMethod.CreateErrorDialog("PLC is Not Started") + def GetCurrentState(self, event): """ Timer event handler for periodic slave state monitoring (Default period: 1 sec = 1000 msec). @@ -268,8 +268,8 @@ try : self.SetCurrentState(line[self.Controler.GetSlavePos()]) except Exception: - pass - + pass + def SetCurrentState(self, line): """ Show current slave state using the executiob result of "ethercat slaves" command. @@ -281,10 +281,10 @@ # Result example : 0 0:0 PREOP + EL9800 (V4.30) (PIC24, SPI, ET1100) token = line.split(" ") if token[2] in state_array: - self.TextCtrlDic["CurrentState"].SetValue(token[2]) + self.TextCtrlDic["CurrentState"].SetValue(token[2]) except Exception: - pass - + pass + def StartTimer(self, event): """ Event handler for "Start State Monitoring" button. @@ -294,7 +294,7 @@ self.SlaveStateThread = wx.Timer(self) # set timer period (1000 ms) self.SlaveStateThread.Start(1000) - + def CurrentStateThreadStop(self, event): """ Event handler for "Stop State Monitoring" button. @@ -305,10 +305,10 @@ self.SlaveStateThread.Stop() except Exception: pass - + #------------------------------------------------------------------------------- # For SDO Management Panel -#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- class SDOPanelClass(wx.Panel): def __init__(self, parent, controler): """ @@ -317,64 +317,64 @@ @param controler: _EthercatSlaveCTN class in EthercatSlave.py """ wx.Panel.__init__(self, parent, -1) - + self.DatatypeDescription, self.CommunicationObject, self.ManufacturerSpecific, \ self.ProfileSpecific, self.Reserved, self.AllSDOData = range(6) - + self.Controler = controler - + self.SDOManagementMainSizer = wx.BoxSizer(wx.VERTICAL) self.SDOManagementInnerMainSizer = wx.FlexGridSizer(cols=1, hgap=10, rows=2, vgap=10) - - self.SDOUpdate = wx.Button(self, label=_('update')) + + self.SDOUpdate = wx.Button(self, label=_('update')) self.SDOUpdate.Bind(wx.EVT_BUTTON, self.SDOInfoUpdate) - + self.CallSDONoteBook = SDONoteBook(self, controler=self.Controler) self.SDOManagementInnerMainSizer.Add(self.SDOUpdate) - self.SDOManagementInnerMainSizer.Add(self.CallSDONoteBook, wx.ALL | wx.EXPAND) + self.SDOManagementInnerMainSizer.Add(self.CallSDONoteBook, wx.ALL | wx.EXPAND) self.SDOManagementMainSizer.Add(self.SDOManagementInnerMainSizer) - + self.SetSizer(self.SDOManagementMainSizer) - + def SDOInfoUpdate(self, event): """ Evenet handler for SDO "update" button. - - Load SDO data from current slave + - Load SDO data from current slave @param event : wx.EVT_BUTTON object - """ + """ self.Controler.CommonMethod.SaveSDOData = [] self.Controler.CommonMethod.ClearSDODataSet() self.SDOFlag = False - + # Check whether beremiz connected or not. check_connect_flag = self.Controler.CommonMethod.CheckConnect(False) if check_connect_flag: self.SDOs = self.Controler.CommonMethod.GetSlaveSDOFromSlave() # SDOFlag is "False", user click "Cancel" button - self.SDOFlag = self.SDOParser() + self.SDOFlag = self.SDOParser() if self.SDOFlag : - self.CallSDONoteBook.CreateNoteBook() + self.CallSDONoteBook.CreateNoteBook() self.Refresh() - - def SDOParser(self): + + def SDOParser(self): """ Parse SDO data set that obtain "SDOInfoUpdate" Method - @return True or False - """ + @return True or False + """ slaveSDO_progress = wx.ProgressDialog("Slave SDO Monitoring", "Now Uploading...", maximum = len(self.SDOs.splitlines()), parent=self, - style = wx.PD_CAN_ABORT | wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME | - wx.PD_ESTIMATED_TIME | wx.PD_REMAINING_TIME | - wx.PD_AUTO_HIDE | wx.PD_SMOOTH) - + style = wx.PD_CAN_ABORT | wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME | + wx.PD_ESTIMATED_TIME | wx.PD_REMAINING_TIME | + wx.PD_AUTO_HIDE | wx.PD_SMOOTH) + # If keep_going flag is False, SDOParser method is stop and return "False". keep_going = True count = 0 - - # SDO data example + + # SDO data example # SDO 0x1000, "Device type" # 0x1000:00,r-r-r-,uint32,32 bit,"Device type",0x00020192, 131474 for details_line in self.SDOs.splitlines(): @@ -387,64 +387,64 @@ else : # line_token = ['0x1000:00,r-r-r-,uint32,32 bit,', 'Device type', ',0x00020192, 131474'] token_head, name, token_tail = line_token - + # token_head = ['0x1000:00', 'r-r-r-', 'uint32', '32 bit', ''] token_head = token_head.split(",") ful_idx, access, type, size, empty = token_head # ful_idx.split(":") = ['0x1000', '00'] idx, sub_idx = ful_idx.split(":") - + # token_tail = ['', '0x00020192', '131474'] token_tail = token_tail.split(",") try : empty, hex_val, dec_val = token_tail - + # SDO data is not return "dec value" - # line example : - # 0x1702:01,rwr-r-,uint32,32 bit," 1st mapping", ---- + # line example : + # 0x1702:01,rwr-r-,uint32,32 bit," 1st mapping", ---- except Exception: empty, hex_val = token_tail - + name_after_check = self.StringTest(name) - + # convert hex type sub_idx = "0x" + sub_idx if type == "octet_string": hex_val = ' ---- ' - + # SResult of SlaveSDO data parsing. (data type : dictionary) - self.Data = {'idx':idx.strip(), 'subIdx':sub_idx.strip(), 'access':access.strip(), - 'type':type.strip(), 'size':size.strip(), 'name':name_after_check.strip("\""), + self.Data = {'idx':idx.strip(), 'subIdx':sub_idx.strip(), 'access':access.strip(), + 'type':type.strip(), 'size':size.strip(), 'name':name_after_check.strip("\""), 'value':hex_val.strip(), "category":title_name.strip("\"")} - + category_divide_value = [0x1000, 0x2000, 0x6000, 0xa000, 0xffff] for count in range(len(category_divide_value)) : if int(idx, 0) < category_divide_value[count]: self.Controler.CommonMethod.SaveSDOData[count].append(self.Data) break - + self.Controler.CommonMethod.SaveSDOData[self.AllSDOData].append(self.Data) - + if count >= len(self.SDOs.splitlines()) / 2: (keep_going, skip) = slaveSDO_progress.Update(count, "Please waiting a moment!!") else: (keep_going, skip) = slaveSDO_progress.Update(count) - - # If user click "Cancel" loop suspend immediately + + # If user click "Cancel" loop suspend immediately if (keep_going == False): break - - slaveSDO_progress.Destroy() - return keep_going + + slaveSDO_progress.Destroy() + return keep_going def StringTest(self, check_string): """ - Test value 'name' is alphanumeric - @param check_string : input data for check + Test value 'name' is alphanumeric + @param check_string : input data for check @return result : output data after check - """ + """ # string.printable is print this result #'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ #!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c @@ -456,11 +456,11 @@ result = check_string[:len(check_string) - i] break return result - - + + #------------------------------------------------------------------------------- # For SDO Notebook (divide category) -#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- class SDONoteBook(wx.Notebook): def __init__(self, parent, controler): """ @@ -468,23 +468,23 @@ @param parent: Reference to the parent SDOPanelClass class @param controler: _EthercatSlaveCTN class in EthercatSlave.py """ - wx.Notebook.__init__(self, parent, id = -1, size=(850,500)) + wx.Notebook.__init__(self, parent, id = -1, size=(850,500)) self.Controler = controler self.parent = parent - + self.CreateNoteBook() - + self.Bind(wx.EVT_CHOICEBOOK_PAGE_CHANGED, self.OnPageChanged) self.Bind(wx.EVT_CHOICEBOOK_PAGE_CHANGING, self.OnPageChanging) - - def CreateNoteBook(self): + + def CreateNoteBook(self): """ Create each NoteBook page, divided SDO index According to EtherCAT Communication(03/2011), 158p - """ + """ self.Data = [] count = 1 - + page_texts = [("all", self.parent.AllSDOData), ("0x0000 - 0x0ff", self.parent.DatatypeDescription), ("0x1000 - 0x1fff", self.parent.CommunicationObject), @@ -500,12 +500,12 @@ "All SDO Object"] self.DeleteAllPages() - + for txt, count in page_texts: self.Data = self.Controler.CommonMethod.SaveSDOData[count] - self.Win = SlaveSDOTable(self, self.Data) + self.Win = SlaveSDOTable(self, self.Data) self.AddPage(self.Win, txt) - + def OnPageChanged(self, event): old = event.GetOldSelection() new = event.GetSelection() @@ -520,17 +520,17 @@ #------------------------------------------------------------------------------- # For SDO Grid (fill index, subindex, etc...) -#------------------------------------------------------------------------------- -class SlaveSDOTable(wx.grid.Grid): +#------------------------------------------------------------------------------- +class SlaveSDOTable(wx.grid.Grid): def __init__(self, parent, data): """ Constructor @param parent: Reference to the parent SDOPanelClass class @param data: SDO data after parsing "SDOParser" method """ - wx.grid.Grid.__init__(self, parent, -1, size=(830,490), + wx.grid.Grid.__init__(self, parent, -1, size=(830,490), style=wx.EXPAND|wx.ALIGN_CENTRE_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL) - + self.Controler = parent.Controler self.parent = parent self.SDOFlag = True @@ -538,55 +538,55 @@ self.SDOs = [] else : self.SDOs = data - + self.CreateGrid(len(self.SDOs), 8) - SDOCellSize = [(0, 65), (1, 65), (2, 50), (3, 55), + SDOCellSize = [(0, 65), (1, 65), (2, 50), (3, 55), (4, 40), (5, 200), (6, 250), (7, 85)] - + for (index, size) in SDOCellSize: self.SetColSize(index, size) - + self.SetRowLabelSize(0) - + SDOTableLabel = [(0, "Index"), (1, "Subindex"), (2, "Access"), (3, "Type"), (4, "Size"), (5, "Category"), (6, "Name"), (7, "Value")] - + for (index, label) in SDOTableLabel: self.SetColLabelValue(index, label) self.SetColLabelAlignment(index, wx.ALIGN_CENTRE) - + attr = wx.grid.GridCellAttr() - # for SDO download + # for SDO download self.Bind(gridlib.EVT_GRID_CELL_LEFT_DCLICK, self.SDOModifyDialog) - - for i in range(7): - self.SetColAttr(i,attr) - + + for i in range(7): + self.SetColAttr(i,attr) + self.SetColLabelAlignment(wx.ALIGN_CENTER, wx.ALIGN_CENTER) - - self.SetTableValue() - + + self.SetTableValue() + def SetTableValue(self): """ Cell is filled by new parsing data """ sdo_list = ['idx', 'subIdx', 'access', 'type', 'size', 'category', 'name', 'value'] for row_idx in range(len(self.SDOs)): - for col_idx in range(len(self.SDOs[row_idx])): + for col_idx in range(len(self.SDOs[row_idx])): self.SetCellValue(row_idx, col_idx, self.SDOs[row_idx][sdo_list[col_idx]]) self.SetReadOnly(row_idx, col_idx, True) if col_idx < 5 : self.SetCellAlignment(row_idx, col_idx, wx.ALIGN_CENTRE, wx.ALIGN_CENTRE) - + def CheckSDODataAccess(self, row): """ CheckSDODataAccess method is checking that access data has "w" Access field consist 6 char, if mean rw rw rw - (preop) (safeop) (op) - Example Access field : rwrwrw, rwrw-- + (preop) (safeop) (op) + Example Access field : rwrwrw, rwrw-- @param row : Selected cell by user @return Write_flag : If data has "w", flag is true """ @@ -595,23 +595,23 @@ if check[1:2] == 'w' : self.Controler.CommonMethod.Check_PREOP = True write_flag = True - if check[3:4] == 'w' : + if check[3:4] == 'w' : self.Controler.CommonMethod.Check_SAFEOP = True write_flag = True if check[5:] =='w' : self.Controler.CommonMethod.Check_OP = True write_flag = True - + return write_flag - + def DecideSDODownload(self, state): """ - compare current state and "access" field, + compare current state and "access" field, result notify SDOModifyDialog method @param state : current slave state @return True or False """ - # Example of 'state' parameter : "0 0:0 PREOP + EL9800 (V4.30) (PIC24, SPI, ET1100)" + # Example of 'state' parameter : "0 0:0 PREOP + EL9800 (V4.30) (PIC24, SPI, ET1100)" state = state[self.Controler.GetSlavePos()].split(" ")[2] if state == "PREOP" and self.Controler.CommonMethod.Check_PREOP : return True @@ -619,9 +619,9 @@ return True elif state == "OP" and self.Controler.CommonMethod.Check_OP : return True - + return False - + def ClearStateFlag(self): """ Initialize StateFlag @@ -630,45 +630,45 @@ self.Controler.CommonMethod.Check_PREOP = False self.Controler.CommonMethod.Check_SAFEOP = False self.Controler.CommonMethod.Check_OP = False - + def SDOModifyDialog (self, event): """ Create dialog for SDO value modify - if user enter data, perform command "ethercat download" + if user enter data, perform command "ethercat download" @param event : gridlib.EVT_GRID_CELL_LEFT_DCLICK object """ self.ClearStateFlag() - - # CheckSDODataAccess is checking that OD(Object Dictionary) has "w" - if event.GetCol() == 7 and self.CheckSDODataAccess(event.GetRow()) : + + # CheckSDODataAccess is checking that OD(Object Dictionary) has "w" + if event.GetCol() == 7 and self.CheckSDODataAccess(event.GetRow()) : dlg = wx.TextEntryDialog (self, "Enter hex or dec value (if enter dec value, it automatically conversed hex value)", "SDOModifyDialog", style = wx.OK | wx.CANCEL) - start_value = self.GetCellValue(event.GetRow(), event.GetCol()) + start_value = self.GetCellValue(event.GetRow(), event.GetCol()) dlg.SetValue(start_value) - + if dlg.ShowModal() == wx.ID_OK: try : int(dlg.GetValue(), 0) # check "Access" field if self.DecideSDODownload(self.Controler.CommonMethod.SlaveState[self.Controler.GetSlavePos()]) : # Request "SDODownload" - self.Controler.CommonMethod.SDODownload(self.SDOs[event.GetRow()]['type'], self.SDOs[event.GetRow()]['idx'], + self.Controler.CommonMethod.SDODownload(self.SDOs[event.GetRow()]['type'], self.SDOs[event.GetRow()]['idx'], self.SDOs[event.GetRow()]['subIdx'], dlg.GetValue()) self.SetCellValue(event.GetRow(), event.GetCol(), hex(int(dlg.GetValue(), 0))) else : - self.Controler.CommonMethod.CreateErrorDialog('You cannot SDO download this state') + self.Controler.CommonMethod.CreateErrorDialog('You cannot SDO download this state') # Error occured process of "int(variable)" # User input is not hex, dec value except ValueError: - self.Controler.CommonMethod.CreateErrorDialog('You can input only hex, dec value') + self.Controler.CommonMethod.CreateErrorDialog('You can input only hex, dec value') #------------------------------------------------------------------------------- # For PDO Monitoring Panel -# PDO Class UI : Panel -> Choicebook (RxPDO, TxPDO) -> +# PDO Class UI : Panel -> Choicebook (RxPDO, TxPDO) -> # Notebook (PDO Index) -> Grid (PDO entry) -#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- class PDOPanelClass(wx.Panel): def __init__(self, parent, controler): """ @@ -681,12 +681,12 @@ self.PDOMonitoringEditorMainSizer = wx.BoxSizer(wx.VERTICAL) self.PDOMonitoringEditorInnerMainSizer = wx.FlexGridSizer(cols=1, hgap=10, rows=2, vgap=10) - - self.CallPDOChoicebook = PDOChoicebook(self, controler=self.Controler) - self.PDOMonitoringEditorInnerMainSizer.Add(self.CallPDOChoicebook, wx.ALL) - + + self.CallPDOChoicebook = PDOChoicebook(self, controler=self.Controler) + self.PDOMonitoringEditorInnerMainSizer.Add(self.CallPDOChoicebook, wx.ALL) + self.PDOMonitoringEditorMainSizer.Add(self.PDOMonitoringEditorInnerMainSizer) - + self.SetSizer(self.PDOMonitoringEditorMainSizer) def PDOInfoUpdate(self): @@ -701,7 +701,7 @@ #------------------------------------------------------------------------------- # For PDO Choicebook (divide Tx, Rx PDO) -#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- class PDOChoicebook(wx.Choicebook): def __init__(self, parent, controler): """ @@ -711,15 +711,15 @@ """ wx.Choicebook.__init__(self, parent, id=-1, size=(500, 500), style=wx.CHB_DEFAULT) self.Controler = controler - + RxWin = PDONoteBook(self, controler=self.Controler, name="Rx") TxWin = PDONoteBook(self, controler=self.Controler, name="Tx") self.AddPage(RxWin, "RxPDO") self.AddPage(TxWin, "TxPDO") - + self.Bind(wx.EVT_CHOICEBOOK_PAGE_CHANGED, self.OnPageChanged) self.Bind(wx.EVT_CHOICEBOOK_PAGE_CHANGING, self.OnPageChanging) - + def OnPageChanged(self, event): old = event.GetOldSelection() new = event.GetSelection() @@ -730,12 +730,12 @@ old = event.GetOldSelection() new = event.GetSelection() sel = self.GetSelection() - event.Skip() + event.Skip() #------------------------------------------------------------------------------- # For PDO Notebook (divide PDO index) -#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- class PDONoteBook(wx.Notebook): def __init__(self, parent, name, controler): """ @@ -746,12 +746,12 @@ """ wx.Notebook.__init__(self, parent, id=-1, size=(640, 400)) self.Controler = controler - + count = 0 page_texts = [] - + self.Controler.CommonMethod.RequestPDOInfo() - + if name == "Tx" : # obtain pdo_info and pdo_entry # pdo_info include (PDO index, name, number of entry) @@ -761,22 +761,22 @@ title = str(hex(tmp['pdo_index'])) page_texts.append(title) # RX PDO case - else : + else : pdo_info = self.Controler.CommonMethod.GetRxPDOCategory() pdo_entry = self.Controler.CommonMethod.GetRxPDOInfo() for tmp in pdo_info : title = str(hex(tmp['pdo_index'])) page_texts.append(title) - + # Add page depending on the number of pdo_info for txt in page_texts: win = PDOEntryTable(self, pdo_info, pdo_entry, count) self.AddPage(win, txt) - count += 1 + count += 1 self.Bind(wx.EVT_CHOICEBOOK_PAGE_CHANGED, self.OnPageChanged) self.Bind(wx.EVT_CHOICEBOOK_PAGE_CHANGING, self.OnPageChanging) - + def OnPageChanged(self, event): old = event.GetOldSelection() new = event.GetSelection() @@ -787,12 +787,12 @@ old = event.GetOldSelection() new = event.GetSelection() sel = self.GetSelection() - event.Skip() + event.Skip() #------------------------------------------------------------------------------- # For PDO Grid (fill entry index, subindex etc...) -#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- class PDOEntryTable(wx.grid.Grid): def __init__(self, parent, info, entry, count): """ @@ -802,38 +802,38 @@ @param entry : data structure including index, name, entry number @param count : page number """ - wx.grid.Grid.__init__(self, parent, -1, size=(500, 400), pos=wx.Point(0,0), + wx.grid.Grid.__init__(self, parent, -1, size=(500, 400), pos=wx.Point(0,0), style=wx.EXPAND|wx.ALIGN_CENTRE_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL) - + self.Controler = parent.Controler - + self.PDOInfo = info self.PDOEntry = entry self.Count = count - + self.CreateGrid(self.PDOInfo[self.Count]['number_of_entry'], 5) - self.SetColLabelSize(25) + self.SetColLabelSize(25) self.SetRowLabelSize(0) - + PDOTableLabel = [(0, "Index"), (1, "Subindex"), (2, "Length"), (3, "Type"), (4, "Name")] - + for (index, label) in PDOTableLabel: self.SetColLabelValue(index, label) - + PDOCellSize = [(0, 45), (1, 65), (2, 55), (3, 40), (4, 300)] - + for (index, size) in PDOCellSize: self.SetColSize(index, size) self.SetColLabelAlignment(index, wx.ALIGN_LEFT) - + attr = wx.grid.GridCellAttr() - + for i in range(5): self.SetColAttr(i, attr) - + self.SetTableValue() - + def SetTableValue(self): """ Cell is filled by new parsing data in XML @@ -844,7 +844,7 @@ list_index += self.PDOInfo[i]['number_of_entry'] start_value = list_index - self.PDOInfo[self.Count]['number_of_entry'] - + pdo_list = ['entry_index', 'subindex', 'bitlen', 'type', 'name'] for row_idx in range(self.PDOInfo[self.Count]['number_of_entry']): for col_idx in range(len(self.PDOEntry[row_idx])): @@ -863,9 +863,9 @@ #------------------------------------------------------------------------------- -# For EEPROM Access Main Panel +# For EEPROM Access Main Panel # (This class explain EEPROM Access) -#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- class EEPROMAccessPanel(wx.Panel): def __init__(self, parent, controler): """ @@ -875,19 +875,19 @@ """ wx.Panel.__init__(self, parent, -1) sizer = wx.FlexGridSizer(cols=1, hgap=20,rows=3, vgap=20) - + line = wx.StaticText(self, -1, "\n EEPROM Access is composed to SmartView and HexView. \ \n\n - SmartView shows Config Data, Device Identity, Mailbox settings, etc. \ \n\n - HexView shows EEPROM's contents.") - + sizer.Add(line) - + self.SetSizer(sizer) #------------------------------------------------------------------------------- -# For Smart View Panel -#------------------------------------------------------------------------------- +# For Smart View Panel +#------------------------------------------------------------------------------- class SlaveSiiSmartView(wx.Panel): def __init__(self, parent, controler): """ @@ -898,8 +898,8 @@ wx.Panel.__init__(self, parent, -1) self.parent = parent self.Controler = controler - - self.PDIType = {0 :['none', '00000000'], + + self.PDIType = {0 :['none', '00000000'], 4 :['Digital I/O', '00000100'], 5 :['SPI Slave', '00000101'], 7 :['EtherCAT Bridge (port3)', '00000111'], @@ -914,7 +914,7 @@ 20 :['0 Digtal Input and 32 Digital Output', '00010100'], 128:['On-chip bus', '11111111'] } - + sizer = wx.FlexGridSizer(cols=1, hgap=5, rows=2, vgap=5) button_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=1, vgap=5) @@ -923,78 +923,78 @@ btn = wx.Button(self, -1, button, size=(150, 40)) button_sizer.Add(btn, border=10, flag=wx.ALL) btn.Bind(wx.EVT_BUTTON, mapping_method) - + self.TreeListCtrl = SmartViewTreeListCtrl(self, self.Controler) - + sizer.Add(button_sizer, border=10, flag=wx.ALL) sizer.Add(self.TreeListCtrl, border=10, flag=wx.ALL) self.SetSizer(sizer) - + self.Create_SmartView() - + def Create_SmartView(self): """ SmartView shows information based on XML as initial value. - """ + """ self.Controler.CommonMethod.SmartViewInfosFromXML = self.Controler.CommonMethod.GetSmartViewInfos() self.SetXMLData() - + def WriteToEEPROM(self, event): """ Open binary file (user select) and write the selected binary data to EEPROM @param event : wx.EVT_BUTTON object - """ + """ # Check whether beremiz connected or not, and whether status is "Started" or not. check_connect_flag = self.Controler.CommonMethod.CheckConnect(False) if check_connect_flag: status, count = self.Controler.GetCTRoot()._connector.GetPLCstatus() if status is not "Started": dialog = wx.FileDialog(self, _("Choose a binary file"), os.getcwd(), "", _("bin files (*.bin)|*.bin"), wx.OPEN) - + if dialog.ShowModal() == wx.ID_OK: filepath = dialog.GetPath() try: binfile = open(filepath,"rb") self.SiiBinary = binfile.read() dialog.Destroy() - + self.Controler.CommonMethod.SiiWrite(self.SiiBinary) # refresh data structure kept by master self.Controler.CommonMethod.Rescan() - # save binary data as inner global data of beremiz + # save binary data as inner global data of beremiz # for fast loading when slave plugin node is reopened. self.Controler.CommonMethod.SiiData = self.SiiBinary self.SetEEPROMData() except Exception: self.Controler.CommonMethod.CreateErrorDialog('The file does not exist!') dialog.Destroy() - + def ReadFromEEPROM(self, event): """ Refresh displayed data based on slave EEPROM and save binary file through dialog @param event : wx.EVT_BUTTON object - """ + """ # Check whether beremiz connected or not. check_connect_flag = self.Controler.CommonMethod.CheckConnect(False) if check_connect_flag: self.SiiBinary = self.Controler.CommonMethod.LoadData() self.SetEEPROMData() - dialog = wx.FileDialog(self, _("Save as..."), os.getcwd(), - "slave0.bin", _("bin files (*.bin)|*.bin|All files|*.*"), + dialog = wx.FileDialog(self, _("Save as..."), os.getcwd(), + "slave0.bin", _("bin files (*.bin)|*.bin|All files|*.*"), wx.SAVE|wx.OVERWRITE_PROMPT) - + if dialog.ShowModal() == wx.ID_OK: filepath = dialog.GetPath() binfile = open(filepath,"wb") binfile.write(self.SiiBinary) binfile.close() - + dialog.Destroy() - + def SetXMLData(self): """ Set data based on XML initially - """ + """ # Config Data: EEPROM Size, PDI Type, Device Emulation # Find PDI Type in pdiType dictionary cnt_pdi_type = self.Controler.CommonMethod.SmartViewInfosFromXML["pdi_type"] @@ -1003,14 +1003,14 @@ cnt_pdi_type = self.PDIType[i][0] break # Set Config Data - for treelist, data in [("EEPROM Size (Bytes)", + for treelist, data in [("EEPROM Size (Bytes)", str(self.Controler.CommonMethod.SmartViewInfosFromXML["eeprom_size"])), - ("PDI Type", + ("PDI Type", cnt_pdi_type), - ("Device Emulation", + ("Device Emulation", self.Controler.CommonMethod.SmartViewInfosFromXML["device_emulation"])]: self.TreeListCtrl.Tree.SetItemText(self.TreeListCtrl.ConfigData[treelist], data, 1) - + # Device Identity: Vendor ID, Product Code, Revision No., Serial No. # Set Device Identity for treelist, data in [("Vendor ID", self.Controler.CommonMethod.SmartViewInfosFromXML["vendor_id"]), @@ -1018,30 +1018,30 @@ ("Revision No.", self.Controler.CommonMethod.SmartViewInfosFromXML["revision_no"]), ("Serial No.", self.Controler.CommonMethod.SmartViewInfosFromXML["serial_no"])]: self.TreeListCtrl.Tree.SetItemText(self.TreeListCtrl.DeviceIdentity[treelist], data, 1) - + # Mailbox: Supported Mailbox, Bootstrap Configuration, Standard Configuration # Set Mailbox for treelist, data in [("Supported Mailbox", self.Controler.CommonMethod.SmartViewInfosFromXML["supported_mailbox"]), ("Bootstrap Configuration", ""), ("Standard Configuration", "")]: - self.TreeListCtrl.Tree.SetItemText(self.TreeListCtrl.Mailbox[treelist], data, 1) + self.TreeListCtrl.Tree.SetItemText(self.TreeListCtrl.Mailbox[treelist], data, 1) # Set Bootstrap Configuration: Receive Offset, Receive Size, Send Offset, Send Size for treelist, data in [("Receive Offset", self.Controler.CommonMethod.SmartViewInfosFromXML["mailbox_bootstrapconf_outstart"]), ("Receive Size", self.Controler.CommonMethod.SmartViewInfosFromXML["mailbox_bootstrapconf_outlength"]), ("Send Offset", self.Controler.CommonMethod.SmartViewInfosFromXML["mailbox_bootstrapconf_instart"]), ("Send Size", self.Controler.CommonMethod.SmartViewInfosFromXML["mailbox_bootstrapconf_inlength"])]: - self.TreeListCtrl.Tree.SetItemText(self.TreeListCtrl.BootstrapConfig[treelist], data, 1) + self.TreeListCtrl.Tree.SetItemText(self.TreeListCtrl.BootstrapConfig[treelist], data, 1) # Set Standard Configuration: Receive Offset, Receive Size, Send Offset, Send Size for treelist, data in [("Receive Offset", self.Controler.CommonMethod.SmartViewInfosFromXML["mailbox_standardconf_outstart"]), ("Receive Size", self.Controler.CommonMethod.SmartViewInfosFromXML["mailbox_standardconf_outlength"]), ("Send Offset", self.Controler.CommonMethod.SmartViewInfosFromXML["mailbox_standardconf_instart"]), ("Send Size", self.Controler.CommonMethod.SmartViewInfosFromXML["mailbox_standardconf_inlength"])]: self.TreeListCtrl.Tree.SetItemText(self.TreeListCtrl.StandardConfig[treelist], data, 1) - + def SetEEPROMData(self): """ Set data based on slave EEPROM. - """ + """ # sii_dict = { Parameter : (WordAddress, WordSize) } sii_dict= { 'PDIControl' : ( '0', 1), 'PDIConfiguration' : ( '1', 1), @@ -1071,7 +1071,7 @@ 'Following Category Word Size' : ('41', 1), 'Category Data' : ('42', 1), } - + # Config Data: EEPROM Size, PDI Type, Device Emulation # EEPROM's data in address '0x003f' is Size of EEPROM in KBit-1 eeprom_size = str((int(self.GetWordAddressData( sii_dict.get('Size'),10 ))+1)/8*1024) @@ -1082,13 +1082,13 @@ cnt_pdi_type = self.PDIType[i][0] break # Get Device Emulation - device_emulation = str(bool(int("{:0>16b}".format(int(self.GetWordAddressData( sii_dict.get('PDIControl'),16 ), 16))[7]))) + device_emulation = str(bool(int("{:0>16b}".format(int(self.GetWordAddressData( sii_dict.get('PDIControl'),16 ), 16))[7]))) # Set Config Data for treelist, data in [("EEPROM Size (Bytes)", eeprom_size), ("PDI Type", cnt_pdi_type), ("Device Emulation", device_emulation)]: self.TreeListCtrl.Tree.SetItemText(self.TreeListCtrl.ConfigData[treelist], data, 1) - + # Device Identity: Vendor ID, Product Code, Revision No., Serial No. # Set Device Identity for treelist, data in [("Vendor ID", self.GetWordAddressData( sii_dict.get('VendorID'),16 )), @@ -1096,10 +1096,10 @@ ("Revision No.", self.GetWordAddressData( sii_dict.get('RevisionNumber'),16 )), ("Serial No.", self.GetWordAddressData( sii_dict.get('SerialNumber'),16 ))]: self.TreeListCtrl.Tree.SetItemText(self.TreeListCtrl.DeviceIdentity[treelist], data, 1) - + # Mailbox # EEORPOM's word address '1c' indicates supported mailbox protocol. - # each value of mailbox protocol : + # each value of mailbox protocol : # VoE(0x0020), SoE(0x0010), FoE(0x0008), CoE(0x0004), EoE(0x0002), AoE(0x0001) supported_mailbox = "" mailbox_protocol=["VoE, ", "SoE, ", "FoE, ", "CoE, ", "EoE, ", "AoE, "] @@ -1112,20 +1112,20 @@ for treelist, data in [("Supported Mailbox", supported_mailbox), ("Bootstrap Configuration", ""), ("Standard Configuration", "")]: - self.TreeListCtrl.Tree.SetItemText(self.TreeListCtrl.Mailbox[treelist], data, 1) + self.TreeListCtrl.Tree.SetItemText(self.TreeListCtrl.Mailbox[treelist], data, 1) # Set Bootstrap Configuration: Receive Offset, Receive Size, Send Offset, Send Size for treelist, data in [("Receive Offset", self.GetWordAddressData( sii_dict.get('BootstrapReceiveMailboxOffset'),10 )), ("Receive Size", self.GetWordAddressData( sii_dict.get('BootstrapReceiveMailboxSize'),10 )), ("Send Offset", self.GetWordAddressData( sii_dict.get('BootstrapSendMailboxOffset'),10 )), ("Send Size", self.GetWordAddressData( sii_dict.get('BootstrapSendMailboxSize'),10 ))]: - self.TreeListCtrl.Tree.SetItemText(self.TreeListCtrl.BootstrapConfig[treelist], data, 1) + self.TreeListCtrl.Tree.SetItemText(self.TreeListCtrl.BootstrapConfig[treelist], data, 1) # Set Standard Configuration: Receive Offset, Receive Size, Send Offset, Send Size for treelist, data in [("Receive Offset", self.GetWordAddressData( sii_dict.get('StandardReceiveMailboxOffset'),10 )), ("Receive Size", self.GetWordAddressData( sii_dict.get('StandardReceiveMailboxSize'),10 )), ("Send Offset", self.GetWordAddressData( sii_dict.get('StandardSendMailboxOffset'),10 )), ("Send Size", self.GetWordAddressData( sii_dict.get('StandardSendMailboxSize'),10 ))]: - self.TreeListCtrl.Tree.SetItemText(self.TreeListCtrl.StandardConfig[treelist], data, 1) - + self.TreeListCtrl.Tree.SetItemText(self.TreeListCtrl.StandardConfig[treelist], data, 1) + def MakeStaticBoxSizer(self, boxlabel): """ Make StaticBoxSizer @@ -1136,14 +1136,14 @@ sizer = wx.StaticBoxSizer(box, wx.VERTICAL) return sizer - + def GetWordAddressData(self, dict_tuple, format): """ This method converts word address data from EEPROM binary. @param dict_tuple : element of 'sii_dict' dictionary in SetEEPROMData() @param format : format of data. It can be 16(hex), 10(decimal) and 2(binary). @return formatted value - """ + """ offset = int(str(dict_tuple[0]), 16) * 2 length = int(str(dict_tuple[1]), 16) * 2 list = [] @@ -1151,21 +1151,21 @@ for index in range(length): hexdata = hex(ord(self.SiiBinary[offset + index]))[2:] list.append(hexdata.zfill(2)) - + list.reverse() data = list[0:length] if format == 16: - return '0x' + ''.join(data) + return '0x' + ''.join(data) elif format == 10: return str(int(str(''.join(data)), 16)) - elif format == 2: - ''.join(data) + elif format == 2: + ''.join(data) #------------------------------------------------------------------------------- # For Smart View TreeListCtrl -#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- class SmartViewTreeListCtrl(wx.Panel): def __init__(self, parent, Controler): """ @@ -1175,26 +1175,26 @@ """ wx.Panel.__init__(self, parent, -1, size=(350, 500)) - - self.Tree = wx.gizmos.TreeListCtrl(self, -1, size=(350, 500), + + self.Tree = wx.gizmos.TreeListCtrl(self, -1, size=(350, 500), style=wx.TR_DEFAULT_STYLE |wx.TR_FULL_ROW_HIGHLIGHT |wx.TR_HIDE_ROOT |wx.TR_COLUMN_LINES |wx.TR_ROW_LINES) - + self.Tree.AddColumn("Description", width=200) self.Tree.AddColumn("Value", width=140) self.Tree.SetMainColumn(0) - + self.Root = self.Tree.AddRoot("") - + # Add item # Level 1 nodes self.Level1Nodes = {} for lv1 in ["Config Data", "Device Identity", "Mailbox"]: self.Level1Nodes[lv1] = self.Tree.AppendItem(self.Root, lv1) - + # Level 2 nodes # Config Data self.ConfigData = {} @@ -1208,7 +1208,7 @@ self.Mailbox = {} for lv2 in ["Supported Mailbox", "Bootstrap Configuration", "Standard Configuration"]: self.Mailbox[lv2] = self.Tree.AppendItem(self.Level1Nodes["Mailbox"], lv2) - + # Level 3 nodes # Children of Bootstrap Configuration self.BootstrapConfig = {} @@ -1218,13 +1218,13 @@ self.StandardConfig = {} for lv3 in ["Receive Offset", "Receive Size", "Send Offset", "Send Size"]: self.StandardConfig[lv3] = self.Tree.AppendItem(self.Mailbox["Standard Configuration"], lv3) - + # Expand Tree - for tree in [self.Root, - self.Level1Nodes["Config Data"], - self.Level1Nodes["Device Identity"], + for tree in [self.Root, + self.Level1Nodes["Config Data"], + self.Level1Nodes["Device Identity"], self.Level1Nodes["Mailbox"], - self.Mailbox["Bootstrap Configuration"], + self.Mailbox["Bootstrap Configuration"], self.Mailbox["Standard Configuration"]]: self.Tree.Expand(tree) @@ -1232,7 +1232,7 @@ #------------------------------------------------------------------------------- # For Hex View Panel # shows EEPROM binary as hex data and characters. -#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- class HexView(wx.Panel): def __init__(self, parent, controler): """ @@ -1243,10 +1243,10 @@ wx.Panel.__init__(self, parent, -1) self.parent = parent self.Controler = controler - + self.HexRow = 8 self.HexCol = 17 - + self.HexViewSizer = {"view" : wx.FlexGridSizer(cols=1, hgap=10, rows=2, vgap=10), "siiButton" : wx.BoxSizer()} self.HexViewButton = {} @@ -1256,16 +1256,16 @@ ("Write to File", self.OnButtonWriteToBinFile), ("Read from File", self.OnButtonReadFromBinFile), ("XML to EEPROM Image", self.OnButtonXmlToEEPROMImg)]: - self.HexViewButton[key] = wx.Button(self, -1, key) + self.HexViewButton[key] = wx.Button(self, -1, key) self.HexViewButton[key].Bind(wx.EVT_BUTTON, evt_handler) self.HexViewSizer["siiButton"].Add(self.HexViewButton[key]) self.SiiBinary = self.Controler.CommonMethod.XmlToEeprom() self.HexCode, self.HexRow, self.HexCol = self.Controler.CommonMethod.HexRead(self.SiiBinary) self.SiiGrid = SiiGridTable(self, self.Controler, self.HexRow, self.HexCol) - self.HexViewSizer["view"].AddMany([self.HexViewSizer["siiButton"], self.SiiGrid]) + self.HexViewSizer["view"].AddMany([self.HexViewSizer["siiButton"], self.SiiGrid]) self.SiiGrid.CreateGrid(self.HexRow, self.HexCol) - self.SetSizer(self.HexViewSizer["view"]) + self.SetSizer(self.HexViewSizer["view"]) self.HexViewSizer["view"].FitInside(self.parent.parent) self.parent.parent.FitInside() self.SiiGrid.SetValue(self.HexCode) @@ -1275,7 +1275,7 @@ """ Destroy existing grid and recreate @param row, col : Hex View grid size - """ + """ self.HexViewSizer["view"].Detach(self.SiiGrid) self.SiiGrid.Destroy() self.SiiGrid = SiiGridTable(self, self.Controler, row, col) @@ -1290,7 +1290,7 @@ Load EEPROM data from slave and refresh Hex View grid Binded to 'Sii Upload' button. @param event : wx.EVT_BUTTON object - """ + """ # Check whether beremiz connected or not. check_connect_flag = self.Controler.CommonMethod.CheckConnect(False) if check_connect_flag: @@ -1300,29 +1300,29 @@ self.UpdateSiiGridTable(self.HexRow, self.HexCol) self.SiiGrid.SetValue(self.HexCode) self.SiiGrid.Update() - + def OnButtonSiiDownload(self, event): """ - Write current EEPROM data to slave and refresh data structure kept by master + Write current EEPROM data to slave and refresh data structure kept by master Binded to 'Sii Download' button. @param event : wx.EVT_BUTTON object - """ - # Check whether beremiz connected or not, - # and whether status is "Started" or not. + """ + # Check whether beremiz connected or not, + # and whether status is "Started" or not. check_connect_flag = self.Controler.CommonMethod.CheckConnect(False) if check_connect_flag: status, count = self.Controler.GetCTRoot()._connector.GetPLCstatus() if status is not "Started": self.Controler.CommonMethod.SiiWrite(self.SiiBinary) self.Controler.CommonMethod.Rescan() - + def OnButtonWriteToBinFile(self, event): - """ + """ Save current EEPROM data to binary file through FileDialog Binded to 'Write to File' button. @param event : wx.EVT_BUTTON object - """ - dialog = wx.FileDialog(self, _("Save as..."), os.getcwd(), "slave0.bin", + """ + dialog = wx.FileDialog(self, _("Save as..."), os.getcwd(), "slave0.bin", _("bin files (*.bin)|*.bin|All files|*.*"), wx.SAVE|wx.OVERWRITE_PROMPT) if dialog.ShowModal() == wx.ID_OK: @@ -1330,33 +1330,33 @@ binfile = open(filepath,"wb") binfile.write(self.SiiBinary) binfile.close() - - dialog.Destroy() - + + dialog.Destroy() + def OnButtonReadFromBinFile(self, event): """ Load binary file through FileDialog Binded to 'Read from File' button. @param event : wx.EVT_BUTTON object """ - dialog = wx.FileDialog(self, _("Choose a binary file"), os.getcwd(), "", + dialog = wx.FileDialog(self, _("Choose a binary file"), os.getcwd(), "", _("bin files (*.bin)|*.bin"), wx.OPEN) - + if dialog.ShowModal() == wx.ID_OK: filepath = dialog.GetPath() - + try: binfile = open(filepath, "rb") self.SiiBinary = binfile.read() self.HexCode, self.HexRow, self.HexCol = self.Controler.CommonMethod.HexRead(self.SiiBinary) - self.UpdateSiiGridTable(self.HexRow, self.HexCol) + self.UpdateSiiGridTable(self.HexRow, self.HexCol) self.SiiGrid.SetValue(self.HexCode) self.SiiGrid.Update() except Exception: self.Controler.CommonMethod.CreateErrorDialog('The file does not exist!') - + dialog.Destroy() - + def OnButtonXmlToEEPROMImg(self, event): """ Create EEPROM data based XML data that current imported @@ -1372,8 +1372,8 @@ #------------------------------------------------------------------------------- # For Hex View grid (fill hex data) -#------------------------------------------------------------------------------- -class SiiGridTable(wx.grid.Grid): +#------------------------------------------------------------------------------- +class SiiGridTable(wx.grid.Grid): def __init__(self, parent, controler, row, col): """ Constructor @@ -1384,10 +1384,10 @@ self.parent = parent self.Controler = controler self.Row = row - self.Col = col - - wx.grid.Grid.__init__(self, parent, -1, size=(830,450), - style=wx.ALIGN_CENTRE_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL) + self.Col = col + + wx.grid.Grid.__init__(self, parent, -1, size=(830,450), + style=wx.ALIGN_CENTRE_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL) def SetValue(self, value): """ @@ -1403,28 +1403,28 @@ else: self.SetColLabelValue(col, '%s'%col) self.SetColSize(col, (self.GetSize().x-120)/20) - + # set data into table row = col = 0 - for row_idx in value: + for row_idx in value: col = 0 self.SetRowLabelValue(row, "0x"+"{:0>4x}".format(row*(self.Col-1))) for hex in row_idx: self.SetCellValue(row, col, hex) - - if col == 16: + + if col == 16: self.SetCellAlignment(row, col, wx.ALIGN_LEFT, wx.ALIGN_CENTER) else: self.SetCellAlignment(row, col, wx.ALIGN_CENTRE, wx.ALIGN_CENTER) - + self.SetReadOnly(row, col, True) col = col + 1 row = row + 1 - + #------------------------------------------------------------------------------- # For Register Access Panel -#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- class RegisterAccessPanel(wx.Panel): def __init__(self, parent, controler): """ @@ -1435,31 +1435,31 @@ self.parent = parent self.Controler = controler self.__init_data() - + wx.Panel.__init__(self, parent, -1) - + sizer = wx.FlexGridSizer(cols=1, hgap=20, rows=2, vgap=5) button_sizer = wx.FlexGridSizer(cols=2, hgap=10, rows=1, vgap=10) - + self.ReloadButton = wx.Button(self, -1, "Reload") - self.CompactViewCheckbox = wx.CheckBox(self, -1, "Compact View") + self.CompactViewCheckbox = wx.CheckBox(self, -1, "Compact View") self.RegisterNotebook = RegisterNotebook(self, self.Controler) - + button_sizer.AddMany([self.ReloadButton, self.CompactViewCheckbox]) sizer.AddMany([button_sizer, self.RegisterNotebook]) self.SetSizer(sizer) - + self.ReloadButton.Bind(wx.EVT_BUTTON, self.OnReloadButton) self.CompactViewCheckbox.Bind(wx.EVT_CHECKBOX, self.ToggleCompactViewCheckbox) - + for index in range(4): self.RegisterNotebook.RegPage[index].MainTable.CreateGrid(self.MainRow[index], self.MainCol) self.RegisterNotebook.RegPage[index].MainTable.SetValue(self, 0, index*512, (index+1)*512) - + # data default setting - if self.Controler.CommonMethod.RegData == "": - self.CompactViewCheckbox.Disable() - for index in range(4): + if self.Controler.CommonMethod.RegData == "": + self.CompactViewCheckbox.Disable() + for index in range(4): self.RegisterNotebook.RegPage[index].MainTable.SetValue(self, 0, index*512, (index+1)*512) else: # If data was saved, self.BasicSetData() @@ -1473,22 +1473,22 @@ """ # flag for compact view self.CompactFlag = False - + # main grid의 rows and cols self.MainRow = [512, 512, 512, 512] self.MainCol = 4 - + # main grids' data range self.PageRange = [] for index in range(4): self.PageRange.append([512*index, 512*(index+1)]) - + # Previous value of register data for register description configuration self.PreRegSpec = {"ESCType": "", "FMMUNumber": "", "SMNumber": "", "PDIType": ""} - + def LoadData(self): """ Get data from the register. @@ -1499,26 +1499,26 @@ #return value : 0x11 for index in range(4): self.Controler.CommonMethod.RegData = self.Controler.CommonMethod.RegData + " " + self.Controler.CommonMethod.RegRead("0x"+"{:0>4x}".format(index*1024), "0x0400") - - # store previous value + + # store previous value # (ESC type, port number of FMMU, port number of SM, and PDI type)) for reg_spec in ["ESCType","FMMUNumber","SMNumber", "PDIType"]: self.PreRegSpec[reg_spec] = self.Controler.CommonMethod.CrtRegSpec[reg_spec] - - # update registers' description + + # update registers' description # (ESC type, port number of FMMU, port number of SM, and PDI type) for reg_spec, address in [("ESCType", "0x0000"), ("FMMUNumber", "0x0004"), ("SMNumber", "0x0005"), ("PDIType", "0x0140")]: self.Controler.CommonMethod.CrtRegSpec[reg_spec] = self.Controler.CommonMethod.RegRead(address, "0x0001") - + # Enable compactView checkbox self.CompactViewCheckbox.Enable() - + def BasicSetData(self): """ - Get and save the description of registers. + Get and save the description of registers. It's done by parsing register_information.xml. """ # parse the above register's value @@ -1528,11 +1528,11 @@ # If the value is 0x12, the result is 18 (It's converted to decimal value) self.FMMUNumber = int(self.Controler.CommonMethod.CrtRegSpec["FMMUNumber"], 16) self.SMNumber = int(self.Controler.CommonMethod.CrtRegSpec["SMNumber"], 16) - + # initialize description dictionary of register main table and register sub table. self.RegisterDescriptionDict = {} self.RegisterSubGridDict = {} - + # ./EthercatMaster/register_information.xml contains register description. if wx.Platform == '__WXMSW__': reg_info_file = open("../../EthercatMaster/register_information.xml", 'r') @@ -1540,7 +1540,7 @@ reg_info_file = open("./EthercatMaster/register_information.xml", 'r') reg_info_tree = minidom.parse(reg_info_file) reg_info_file.close() - + # parse register description for register_info in reg_info_tree.childNodes: for register in register_info.childNodes: @@ -1550,7 +1550,7 @@ ("pdi", "type", self.PDIType), ("fmmu", "number", self.FMMUNumber), ("sm", "number", self.SMNumber)]: - if property in register.attributes.keys(): + if property in register.attributes.keys(): if type == "type": if register.attributes[property].value == value: self.GetRegisterInfo(reg_info_tree, register) @@ -1562,7 +1562,7 @@ else: self.GetRegisterInfo(reg_info_tree, register) break - + def GetRegisterInfo(self, reg_info_tree, register): """ Save the register's description into the dictionary. @@ -1573,7 +1573,7 @@ # temporary variables for register main table idescription dictionary reg_index = "" reg_main_description = "" - + for data in register.childNodes: if data.nodeType == reg_info_tree.ELEMENT_NODE and data.nodeName == "Index": for index in data.childNodes: @@ -1581,15 +1581,15 @@ if data.nodeType == reg_info_tree.ELEMENT_NODE and data.nodeName == "Description": for description in data.childNodes: reg_main_description = description.nodeValue - - # Add description for register main table + + # Add description for register main table if reg_index is not "" and reg_main_description is not "": self.RegisterDescriptionDict[reg_index] = reg_main_description - + if data.nodeType == reg_info_tree.ELEMENT_NODE and data.nodeName == "Details": # declare register sub table description dictionary about this index self.RegisterSubGridDict[reg_index] = [] - + for detail in data.childNodes: if detail.nodeType == reg_info_tree.ELEMENT_NODE and detail.nodeName == "Detail": # If it depends on the property(ESC type, PDI type, FMMU number, SM number) @@ -1597,7 +1597,7 @@ ("pdi", "type", self.PDIType), ("fmmu", "number", self.FMMUNumber), ("sm", "number", self.SMNumber)]: - if property in detail.attributes.keys(): + if property in detail.attributes.keys(): if type == "type": if detail.attributes[property].value == value: self.GetRegisterDetailInfo(reg_info_tree, reg_index, detail) @@ -1609,7 +1609,7 @@ else: self.GetRegisterDetailInfo(reg_info_tree, reg_index, detail) break - + def GetRegisterDetailInfo(self, reg_info_tree, reg_index, detail): """ Get the resgister's detailed description(for sub table) from the reg_info_tree. @@ -1617,30 +1617,30 @@ @param reg_index: index of the register @param detail: description of the register """ - # temporary variables for register sub table description dictionary - # - It is initialized in every sub description + # temporary variables for register sub table description dictionary + # - It is initialized in every sub description reg_bit_range = "" reg_sub_description = "" reg_enum_dictionary = {} - + for detail_data in detail.childNodes: - if detail_data.nodeType == reg_info_tree.ELEMENT_NODE and detail_data.nodeName == "Range": + if detail_data.nodeType == reg_info_tree.ELEMENT_NODE and detail_data.nodeName == "Range": for range in detail_data.childNodes: reg_bit_range = range.nodeValue if detail_data.nodeType == reg_info_tree.ELEMENT_NODE and detail_data.nodeName == "Description": for description in detail_data.childNodes: reg_sub_description = description.nodeValue - + if detail_data.nodeType == reg_info_tree.ELEMENT_NODE and detail_data.nodeName == "Enum": for enum in detail_data.childNodes: if enum.nodeType == reg_info_tree.ELEMENT_NODE and enum.nodeName == "item": - - # temporary variables for a description of each value - # For example, if the bit is 1, it is 'enabled'('On', 'True', etc.), - # otherwise 'disabled'('Off', 'False', etc.). + + # temporary variables for a description of each value + # For example, if the bit is 1, it is 'enabled'('On', 'True', etc.), + # otherwise 'disabled'('Off', 'False', etc.). reg_sub_value = "" reg_sub_value_description = "" - + for item in enum.childNodes: if item.nodeType == reg_info_tree.ELEMENT_NODE and item.nodeName == "value": for value in item.childNodes: @@ -1648,16 +1648,16 @@ if item.nodeType == reg_info_tree.ELEMENT_NODE and item.nodeName == "Description": for description in item.childNodes: reg_sub_value_description = description.nodeValue - + # Add a description of each value to register enum dictionary if reg_sub_value is not "" and reg_sub_value_description is not "": reg_enum_dictionary[reg_sub_value] = reg_sub_value_description - + # add a description to register sub table description dictionary if reg_bit_range is not "" and reg_sub_description is not "": - self.RegisterSubGridDict[reg_index].append([reg_bit_range, + self.RegisterSubGridDict[reg_index].append([reg_bit_range, reg_sub_description, reg_enum_dictionary]) - + def ParseData(self): """ Transform the data into dec, hex, string, and description @@ -1665,30 +1665,30 @@ row_data = [] self.RegMonitorData = [] reg_word = "" - + reg_data = self.Controler.CommonMethod.RegData.split() - + # loop for register(0x0000:0x0fff) for address in range(0x1000): - # arrange 2 Bytes of register data + # arrange 2 Bytes of register data reg_word = reg_data[address].split('x')[1] + reg_word if (address%2) == 1: # append address hex_address = "{:0>4x}".format(address-1) row_data.append(hex_address) - + # append description if self.RegisterDescriptionDict.has_key(hex_address): row_data.append(self.RegisterDescriptionDict[hex_address]) else: row_data.append("") - + # append Decimal value row_data.append(str(int(reg_word, 16))) - + # append Hex value row_data.append('0x'+reg_word) - + # append ASCII value char_data = "" for iter in range(2): @@ -1697,11 +1697,11 @@ else: char_data = char_data + "." row_data.append(char_data) - + self.RegMonitorData.append(row_data) reg_word = "" # initialize regWord row_data = [] - + def OnReloadButton(self, event): """ Handle the click event of the 'Reload' button. @@ -1717,10 +1717,10 @@ # set data into UI if self.CompactFlag: self.ToggleCompactViewCheckbox(True) - else : + else : for index in range(4): - self.RegisterNotebook.RegPage[index].UpdateMainTable(self.MainRow[index], self.MainCol, - self.PageRange[index][0], self.PageRange[index][1], + self.RegisterNotebook.RegPage[index].UpdateMainTable(self.MainRow[index], self.MainCol, + self.PageRange[index][0], self.PageRange[index][1], self.RegMonitorData) def ToggleCompactViewCheckbox(self, event): @@ -1730,12 +1730,12 @@ If not, show all the registers. @param event: wx.EVT_CHECKBOX object """ - + # If "Compact View" Checkbox is True ## 'event' is argument of this method or event of checkbox. if event==True or event.GetEventObject().GetValue(): self.CompactFlag = True - + reg_compact_data = [] page_row = [0, 0, 0, 0] for index in range(4): @@ -1758,34 +1758,34 @@ self.PageRange[index][1] = page_row[index] for iter in range(index): self.PageRange[index][0] += page_row[iter] - self.PageRange[index][1] += page_row[iter] - + self.PageRange[index][1] += page_row[iter] + # Update table for index in range(4): - self.RegisterNotebook.RegPage[index].UpdateMainTable(self.MainRow[index], self.MainCol, - self.PageRange[index][0], self.PageRange[index][1], + self.RegisterNotebook.RegPage[index].UpdateMainTable(self.MainRow[index], self.MainCol, + self.PageRange[index][0], self.PageRange[index][1], reg_compact_data) - - # Compact View Checkbox is False + + # Compact View Checkbox is False else: self.CompactFlag = False # Setting original rows, cols and range self.MainRow = [512, 512, 512, 512] self.PageRange = [] - + for index in range(4): self.PageRange.append([512*index, 512*(index+1)]) - - # Update table + + # Update table for index in range(4): - self.RegisterNotebook.RegPage[index].UpdateMainTable(self.MainRow[index], self.MainCol, - self.PageRange[index][0], self.PageRange[index][1], + self.RegisterNotebook.RegPage[index].UpdateMainTable(self.MainRow[index], self.MainCol, + self.PageRange[index][0], self.PageRange[index][1], self.RegMonitorData) - + #------------------------------------------------------------------------------- # For Register Access Notebook (divide index range) -#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- class RegisterNotebook(wx.Notebook): def __init__(self, parent, controler): """ @@ -1794,21 +1794,21 @@ @param controler: _EthercatSlaveCTN class in EthercatSlave.py """ wx.Notebook.__init__(self, parent, id = -1) - + self.parent = parent self.Controler = controler - + # Initialize pages self.RegPage = [] for iter in range(4): self.RegPage.append(None) - + for index in range(4): - self.RegPage[index] = RegisterNotebookPanel(self, self.Controler, + self.RegPage[index] = RegisterNotebookPanel(self, self.Controler, parent.MainRow[index], parent.MainCol) - self.AddPage(self.RegPage[index], + self.AddPage(self.RegPage[index], "0x"+"{:0>4x}".format(index*1024)+" - 0x"+"{:0>4x}".format((index+1)*1024-1)) - + self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged) self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self.OnPageChanging) @@ -1826,9 +1826,9 @@ #------------------------------------------------------------------------------- -# For Register Access Notebook Panel +# For Register Access Notebook Panel # (Main UI : including main, sub table) -#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- class RegisterNotebookPanel(wx.Panel): def __init__(self, parent, controler, row, col): """ @@ -1838,26 +1838,26 @@ @param row, col: size of the table """ wx.Panel.__init__(self, parent, -1) - + self.parent = parent self.Controler = controler self.Row = row self.Col = col sub_row = 0 sub_col = 4 - + self.Sizer = wx.FlexGridSizer(cols=1, hgap=10, rows=2, vgap=30) - + self.MainTable = RegisterMainTable(self, self.Row, self.Col, self.Controler) self.SubTable = RegisterSubTable(self, sub_row, sub_col) - + self.SubTable.CreateGrid(sub_row, sub_col) self.SubTable.SetValue(self, []) - + self.Sizer.AddMany([self.MainTable, self.SubTable]) - + self.SetSizer(self.Sizer) - + def UpdateMainTable(self, row, col, low_index, high_index, data): """ Updates main table. @@ -1892,13 +1892,13 @@ self.SubTable.CreateGrid(row, col) self.SubTable.SetValue(self, data) self.SubTable.Update() - + #------------------------------------------------------------------------------- # For Register Access Notebook Panel (Main Table) -#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- class RegisterMainTable(wx.grid.Grid): - def __init__(self, parent, row, col, controler): + def __init__(self, parent, row, col, controler): """ Constructor @param parent: RegisterNotebook object @@ -1911,16 +1911,16 @@ self.Col = col self.Controler = controler self.RegisterAccessPanel = self.parent.parent.parent - - wx.grid.Grid.__init__(self, parent, -1, size=(820,300), - style=wx.EXPAND|wx.ALIGN_CENTRE_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL) - + + wx.grid.Grid.__init__(self, parent, -1, size=(820,300), + style=wx.EXPAND|wx.ALIGN_CENTRE_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL) + for evt, mapping_method in [(gridlib.EVT_GRID_CELL_LEFT_CLICK, self.OnSelectCell), (gridlib.EVT_GRID_CELL_LEFT_CLICK, self.OnSelectCell), (gridlib.EVT_GRID_CELL_LEFT_DCLICK, self.OnRegModifyDialog)]: self.Bind(evt, mapping_method) - - def SetValue(self, parent, reg_monitor_data, low_index, high_index): + + def SetValue(self, parent, reg_monitor_data, low_index, high_index): """ Set the RegMonitorData into the main table. @param parent: RegisterNotebook object @@ -1929,21 +1929,21 @@ @param high_index: the highest index of the page """ self.RegMonitorData = reg_monitor_data - + # set label name and size - register_maintable_label = [(0, "Description"), (1, "Dec"), + register_maintable_label = [(0, "Description"), (1, "Dec"), (2, "Hex"), (3, "Char")] - + for (index, label) in register_maintable_label: self.SetColLabelValue(index, label) - + self.SetColSize(0, 200) - + # if reg_monitor_data is 0, it is initialization of register access. if reg_monitor_data == 0: return 0 - - # set data into UI + + # set data into UI row = col = 0 for row_index in reg_monitor_data[low_index:high_index]: col = 0 @@ -1954,8 +1954,8 @@ self.SetReadOnly(row, col, True) col = col + 1 row = row + 1 - - def OnSelectCell(self, event): + + def OnSelectCell(self, event): """ Handles the event of the cell of the main table. @param event: gridlib object (left click) @@ -1964,17 +1964,17 @@ if self.RegMonitorData == 0: event.Skip() return 0 - + sub_row = 0 sub_col = 4 - + address = self.GetRowLabelValue(event.GetRow()) - + reg_sub_grid_data = [] - + BIT_RANGE, NAME, DESCRIPTIONS = range(3) - - # Check if this register's detail description is exist or not, + + # Check if this register's detail description is exist or not, # and create data structure for the detail description table ; sub grid if address in self.RegisterAccessPanel.RegisterSubGridDict: for element in self.RegisterAccessPanel.RegisterSubGridDict[address]: @@ -1991,11 +1991,11 @@ row_data.append('') reg_sub_grid_data.append(row_data) sub_row = sub_row + 1 - + self.parent.UpdateSubTable(sub_row, sub_col, reg_sub_grid_data) # event.Skip() updates UI of selecting cell event.Skip() - + def OnRegModifyDialog(self, event): """ Handle the event of the cell of the main table. @@ -2004,16 +2004,16 @@ """ # user can enter a value in case that user double-clicked 'Dec' or 'Hex' value. if event.GetCol() == 1 or event.GetCol() == 2: - dlg = wx.TextEntryDialog(self, "Enter hex(0xnnnn) or dec(n) value", + dlg = wx.TextEntryDialog(self, "Enter hex(0xnnnn) or dec(n) value", "Register Modify Dialog", style = wx.OK|wx.CANCEL) - + # Setting value in initial dialog value start_value = self.GetCellValue(event.GetRow(), event.GetCol()) dlg.SetValue(start_value) - + if dlg.ShowModal() == wx.ID_OK: try: - # It int(input) success, this input is dev or hex value. + # It int(input) success, this input is dev or hex value. # Otherwise, it's error, so it goes except. int(dlg.GetValue(), 0) @@ -2023,7 +2023,7 @@ if len(return_val)==0: # set dec - self.SetCellValue(event.GetRow(), 1, str(int(dlg.GetValue(), 0))) + self.SetCellValue(event.GetRow(), 1, str(int(dlg.GetValue(), 0))) # set hex hex_data = '0x'+"{:0>4x}".format(int(dlg.GetValue(), 0)) self.SetCellValue(event.GetRow(), 2, hex_data) @@ -2035,19 +2035,19 @@ char_data = char_data + chr(int(hex_data[(iter+1)*2:(iter+2)*2], 16)) else: char_data = char_data + "." - - self.SetCellValue(event.GetRow(), 3, char_data) - + + self.SetCellValue(event.GetRow(), 3, char_data) + else: self.Controler.CommonMethod.CreateErrorDialog('You can\'t modify it. This register is read-only or it\'s not connected.') - + except ValueError: self.Controler.CommonMethod.CreateErrorDialog('You entered wrong value. You can enter dec or hex value only.') - - + + #------------------------------------------------------------------------------- # For Register Access Notebook Panel (Sub Table) -#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- class RegisterSubTable(wx.grid.Grid): def __init__(self, parent, row, col): """ @@ -2060,8 +2060,8 @@ self.Row = row self.Col = col - wx.grid.Grid.__init__(self, parent, -1, size=(820,150), - style=wx.EXPAND|wx.ALIGN_CENTRE_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL) + wx.grid.Grid.__init__(self, parent, -1, size=(820,150), + style=wx.EXPAND|wx.ALIGN_CENTRE_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL) def SetValue(self, parent, data): """ @@ -2070,30 +2070,30 @@ @param data: data """ # lset label name and size - Register_SubTable_Label = [(0, "Bits"), (1, "Name"), + Register_SubTable_Label = [(0, "Bits"), (1, "Name"), (2, "Value"), (3, "Enum")] - + for (index, label) in Register_SubTable_Label: self.SetColLabelValue(index, label) - + self.SetColSize(1, 200) self.SetColSize(3, 200) - + # set data into table row = col = 0 - for rowData in data: - col = 0 + for rowData in data: + col = 0 for element in rowData: self.SetCellValue(row, col, element) self.SetCellAlignment(row, col, wx.ALIGN_CENTRE, wx.ALIGN_CENTER) self.SetReadOnly(row, col, True) col = col + 1 row = row + 1 - + #------------------------------------------------------------------------------- # For Master State Panel -#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- class MasterStatePanelClass(wx.Panel): def __init__(self, parent, controler): """ @@ -2101,14 +2101,14 @@ @param parent: wx.ScrollWindow object @Param controler: _EthercatSlaveCTN class in EthercatSlave.py """ - wx.Panel.__init__(self, parent, -1, (0, 0), + wx.Panel.__init__(self, parent, -1, (0, 0), size=wx.DefaultSize, style = wx.SUNKEN_BORDER) self.Controler = controler self.parent = parent self.StaticBox = {} self.StaticText = {} self.TextCtrl = {} - + # ----------------------- Main Sizer and Update Button -------------------------------------------- self.MasterStateSizer = {"main" : wx.BoxSizer(wx.VERTICAL)} for key, attr in [ @@ -2123,15 +2123,15 @@ self.UpdateButton = wx.Button(self, label=_('Update')) self.UpdateButton.Bind(wx.EVT_BUTTON, self.OnButtonClick) - - for key, label in [ + + for key, label in [ ('masterState', 'EtherCAT Master State'), ('deviceInfo', 'Ethernet Network Card Information'), ('frameInfo', 'Network Frame Information')]: self.StaticBox[key] = wx.StaticBox(self, label=_(label)) self.MasterStateSizer[key] = wx.StaticBoxSizer(self.StaticBox[key]) - - + + # ----------------------- Master State ----------------------------------------------------------- for key, label in [ ('Phase', 'Phase:'), @@ -2139,11 +2139,11 @@ ('Slaves', 'Slave Count:')]: self.StaticText[key] = wx.StaticText(self, label=_(label)) self.TextCtrl[key] = wx.TextCtrl(self, size=wx.Size(130, 24), style=wx.TE_READONLY) - self.MasterStateSizer['innerMasterState'].AddMany([self.StaticText[key], self.TextCtrl[key]]) - + self.MasterStateSizer['innerMasterState'].AddMany([self.StaticText[key], self.TextCtrl[key]]) + self.MasterStateSizer['masterState'].AddSizer(self.MasterStateSizer['innerMasterState']) - - # ----------------------- Ethernet Network Card Information --------------------------------------- + + # ----------------------- Ethernet Network Card Information --------------------------------------- for key, label in [ ('Main', 'MAC Address:'), ('Link', 'Link State:'), @@ -2153,24 +2153,24 @@ self.StaticText[key] = wx.StaticText(self, label=_(label)) self.TextCtrl[key] = wx.TextCtrl(self, size=wx.Size(130, 24), style=wx.TE_READONLY) self.MasterStateSizer['innerDeviceInfo'].AddMany([self.StaticText[key], self.TextCtrl[key]]) - + self.MasterStateSizer['deviceInfo'].AddSizer(self.MasterStateSizer['innerDeviceInfo']) - + # ----------------------- Network Frame Information ----------------------------------------------- for key, label in [ - ('Tx frame rate [1/s]', 'Tx Frame Rate [1/s]:'), - ('Rx frame rate [1/s]', 'Tx Rate [kByte/s]:'), + ('Tx frame rate [1/s]', 'Tx Frame Rate [1/s]:'), + ('Rx frame rate [1/s]', 'Tx Rate [kByte/s]:'), ('Loss rate [1/s]', 'Loss Rate [1/s]:'), ('Frame loss [%]', 'Frame Loss [%]:')]: self.StaticText[key] = wx.StaticText(self, label=_(label)) self.MasterStateSizer['innerFrameInfo'].Add(self.StaticText[key]) - self.TextCtrl[key] = {} - for index in ['0', '1', '2']: + self.TextCtrl[key] = {} + for index in ['0', '1', '2']: self.TextCtrl[key][index] = wx.TextCtrl(self, size=wx.Size(130, 24), style=wx.TE_READONLY) self.MasterStateSizer['innerFrameInfo'].Add(self.TextCtrl[key][index]) - + self.MasterStateSizer['frameInfo'].AddSizer(self.MasterStateSizer['innerFrameInfo']) - + # --------------------------------- Main Sizer ---------------------------------------------------- for key, sub, in [ ('innerTopHalf', [ @@ -2184,7 +2184,7 @@ self.MasterStateSizer['main'].AddSizer(self.UpdateButton) self.MasterStateSizer['main'].AddSizer(self.MasterStateSizer['innerMain']) - + self.SetSizer(self.MasterStateSizer['main']) def OnButtonClick(self, event): diff -r 9460872f1440 -r fec77f2b9e07 etherlab/EthercatCFileGenerator.py --- a/etherlab/EthercatCFileGenerator.py Fri Sep 28 17:15:53 2018 +0300 +++ b/etherlab/EthercatCFileGenerator.py Fri Sep 28 17:20:11 2018 +0300 @@ -72,7 +72,7 @@ entry_infos["data_type"] = DATATYPECONVERSION.get(entry_infos["var_type"], None) if entry_infos["data_type"] is None: raise ValueError, _("Type of location \"%s\" not yet supported!") % entry_infos["var_name"] - + if not entry_infos.get("no_decl", False): if entry_infos.has_key("real_var"): str_completion["located_variables_declaration"].append( @@ -88,40 +88,40 @@ "IEC_%(var_type)s *%(extra_decl)s = &%(real_var)s;" % entry_infos) elif not entry_infos.has_key("real_var"): entry_infos["real_var"] = "beremiz" + entry_infos["var_name"] - + str_completion["used_pdo_entry_offset_variables_declaration"].append( "unsigned int slave%(slave)d_%(index).4x_%(subindex).2x;" % entry_infos) - + if entry_infos["data_type"] == "BIT": str_completion["used_pdo_entry_offset_variables_declaration"].append( "unsigned int slave%(slave)d_%(index).4x_%(subindex).2x_bit;" % entry_infos) - + str_completion["used_pdo_entry_configuration"].append( - (" {%(alias)d, %(position)d, 0x%(vendor).8x, 0x%(product_code).8x, " + - "0x%(index).4x, %(subindex)d, &slave%(slave)d_%(index).4x_%(subindex).2x, " + + (" {%(alias)d, %(position)d, 0x%(vendor).8x, 0x%(product_code).8x, " + + "0x%(index).4x, %(subindex)d, &slave%(slave)d_%(index).4x_%(subindex).2x, " + "&slave%(slave)d_%(index).4x_%(subindex).2x_bit},") % entry_infos) - + if entry_infos["dir"] == "I": str_completion["retrieve_variables"].append( - (" %(real_var)s = EC_READ_BIT(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + + (" %(real_var)s = EC_READ_BIT(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + "slave%(slave)d_%(index).4x_%(subindex).2x_bit);") % entry_infos) elif entry_infos["dir"] == "Q": str_completion["publish_variables"].append( - (" EC_WRITE_BIT(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + + (" EC_WRITE_BIT(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + "slave%(slave)d_%(index).4x_%(subindex).2x_bit, %(real_var)s);") % entry_infos) - + else: str_completion["used_pdo_entry_configuration"].append( - (" {%(alias)d, %(position)d, 0x%(vendor).8x, 0x%(product_code).8x, 0x%(index).4x, " + + (" {%(alias)d, %(position)d, 0x%(vendor).8x, 0x%(product_code).8x, 0x%(index).4x, " + "%(subindex)d, &slave%(slave)d_%(index).4x_%(subindex).2x},") % entry_infos) - + if entry_infos["dir"] == "I": str_completion["retrieve_variables"].append( - (" %(real_var)s = EC_READ_%(data_type)s(domain1_pd + " + + (" %(real_var)s = EC_READ_%(data_type)s(domain1_pd + " + "slave%(slave)d_%(index).4x_%(subindex).2x);") % entry_infos) elif entry_infos["dir"] == "Q": str_completion["publish_variables"].append( - (" EC_WRITE_%(data_type)s(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + + (" EC_WRITE_%(data_type)s(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + "%(real_var)s);") % entry_infos) def ExclusionSortFunction(x, y): @@ -134,22 +134,22 @@ return -cmp(x["matching"], y["matching"]) class _EthercatCFileGenerator: - + def __init__(self, controler): self.Controler = controler - + self.Slaves = [] self.UsedVariables = {} def __del__(self): - self.Controler = None - + self.Controler = None + def DeclareSlave(self, slave_index, slave): self.Slaves.append((slave_index, slave.getInfo().getAutoIncAddr(), slave)) def DeclareVariable(self, slave_index, index, subindex, iec_type, dir, name, no_decl=False): slave_variables = self.UsedVariables.setdefault(slave_index, {}) - + entry_infos = slave_variables.get((index, subindex), None) if entry_infos is None: slave_variables[(index, subindex)] = { @@ -164,16 +164,16 @@ else: raise ValueError, _("Output variables can't be defined with different locations (%s and %s)") % (entry_infos["infos"][2], name) else: - raise ValueError, _("Definition conflict for location \"%s\"") % name - + raise ValueError, _("Definition conflict for location \"%s\"") % name + def GenerateCFile(self, filepath, location_str, master_number): - + # Extract etherlab master code template plc_etherlab_filepath = os.path.join(os.path.split(__file__)[0], "plc_etherlab.c") plc_etherlab_file = open(plc_etherlab_filepath, 'r') plc_etherlab_code = plc_etherlab_file.read() plc_etherlab_file.close() - + # Initialize strings for formatting master code template str_completion = { "location": location_str, @@ -189,49 +189,49 @@ "retrieve_variables": [], "publish_variables": [], } - + # Initialize variable storing variable mapping state for slave_entries in self.UsedVariables.itervalues(): for entry_infos in slave_entries.itervalues(): entry_infos["mapped"] = False - + # Sort slaves by position (IEC_Channel) self.Slaves.sort() # Initialize dictionary storing alias auto-increment position values alias = {} - + # Generating code for each slave for (slave_idx, slave_alias, slave) in self.Slaves: type_infos = slave.getType() - + # Defining slave alias and auto-increment position if alias.get(slave_alias) is not None: alias[slave_alias] += 1 else: alias[slave_alias] = 0 slave_pos = (slave_alias, alias[slave_alias]) - + # Extract slave device informations device, module_extra_params = self.Controler.GetModuleInfos(type_infos) if device is None: raise ValueError, _("No informations found for device %s!") % (type_infos["device_type"]) - + # Extract slaves variables to be mapped slave_variables = self.UsedVariables.get(slave_idx, {}) - + # Extract slave device object dictionary entries device_entries = device.GetEntriesList() - + # Adding code for declaring slave in master code template strings for element in ["vendor", "product_code", "revision_number"]: type_infos[element] = ExtractHexDecValue(type_infos[element]) type_infos.update(dict(zip(["slave", "alias", "position"], (slave_idx,) + slave_pos))) - + # Extract slave device CoE informations device_coe = device.getCoE() if device_coe is not None: - - # If device support CanOpen over Ethernet, adding code for calling + + # If device support CanOpen over Ethernet, adding code for calling # init commands when initializing slave in master code template strings initCmds = [] for initCmd in device_coe.getInitCmd(): @@ -256,37 +256,37 @@ } init_cmd_infos.update(type_infos) str_completion["slaves_initialization"] += SLAVE_INITIALIZATION_TEMPLATE % init_cmd_infos - + # Extract slave device PDO configuration capabilities PdoAssign = device_coe.getPdoAssign() PdoConfig = device_coe.getPdoConfig() else: PdoAssign = PdoConfig = False - + # Test if slave has a configuration or need one if len(device.getTxPdo() + device.getRxPdo()) > 0 or len(slave_variables) > 0 and PdoConfig and PdoAssign: - + str_completion["slaves_declaration"] += "static ec_slave_config_t *slave%(slave)d = NULL;\n" % type_infos str_completion["slaves_configuration"] += SLAVE_CONFIGURATION_TEMPLATE % type_infos - - # Initializing + + # Initializing pdos_infos = { "pdos_entries_infos": [], "pdos_infos": [], - "pdos_sync_infos": [], + "pdos_sync_infos": [], } pdos_infos.update(type_infos) - + sync_managers = [] for sync_manager_idx, sync_manager in enumerate(device.getSm()): sync_manager_infos = { - "index": sync_manager_idx, + "index": sync_manager_idx, "name": sync_manager.getcontent(), "slave": slave_idx, - "pdos": [], + "pdos": [], "pdos_number": 0, } - + sync_manager_control_byte = ExtractHexDecValue(sync_manager.getControlByte()) sync_manager_direction = sync_manager_control_byte & 0x0c sync_manager_watchdog = sync_manager_control_byte & 0x40 @@ -298,50 +298,50 @@ sync_manager_infos["watchdog"] = "EC_WD_ENABLE" else: sync_manager_infos["watchdog"] = "EC_WD_DISABLE" - + sync_managers.append(sync_manager_infos) - + pdos_index = [] exclusive_pdos = {} selected_pdos = [] for pdo, pdo_type in ([(pdo, "Inputs") for pdo in device.getTxPdo()] + [(pdo, "Outputs") for pdo in device.getRxPdo()]): - + pdo_index = ExtractHexDecValue(pdo.getIndex().getcontent()) pdos_index.append(pdo_index) - + excluded_list = pdo.getExclude() if len(excluded_list) > 0: exclusion_list = [pdo_index] for excluded in excluded_list: exclusion_list.append(ExtractHexDecValue(excluded.getcontent())) exclusion_list.sort() - + exclusion_scope = exclusive_pdos.setdefault(tuple(exclusion_list), []) - + entries = pdo.getEntry() pdo_mapping_match = { - "index": pdo_index, - "matching": 0, - "count": len(entries), + "index": pdo_index, + "matching": 0, + "count": len(entries), "assigned": pdo.getSm() is not None } exclusion_scope.append(pdo_mapping_match) - + for entry in entries: index = ExtractHexDecValue(entry.getIndex().getcontent()) subindex = ExtractHexDecValue(entry.getSubIndex()) if slave_variables.get((index, subindex), None) is not None: pdo_mapping_match["matching"] += 1 - + if pdo.getFixed() != True: pdo_mapping_match["matching"] += \ module_extra_params["max_pdo_size"] - \ pdo_mapping_match["count"] - + elif pdo.getMandatory(): selected_pdos.append(pdo_index) - + excluded_pdos = [] for exclusion_scope in exclusive_pdos.itervalues(): exclusion_scope.sort(ExclusionSortFunction) @@ -349,22 +349,22 @@ if exclusion_scope[0]["matching"] > 0: selected_pdos.append(exclusion_scope[0]["index"]) start_excluding_index = 1 - excluded_pdos.extend([pdo["index"] - for pdo in exclusion_scope[start_excluding_index:] + excluded_pdos.extend([pdo["index"] + for pdo in exclusion_scope[start_excluding_index:] if PdoAssign or not pdo["assigned"]]) - + for pdo, pdo_type in ([(pdo, "Inputs") for pdo in device.getTxPdo()] + [(pdo, "Outputs") for pdo in device.getRxPdo()]): entries = pdo.getEntry() - + pdo_index = ExtractHexDecValue(pdo.getIndex().getcontent()) if pdo_index in excluded_pdos: continue - + pdo_needed = pdo_index in selected_pdos - + entries_infos = [] - + for entry in entries: index = ExtractHexDecValue(entry.getIndex().getcontent()) subindex = ExtractHexDecValue(entry.getSubIndex()) @@ -376,30 +376,30 @@ } entry_infos.update(type_infos) entries_infos.append(" {0x%(index).4x, 0x%(subindex).2x, %(bitlen)d}, /* %(name)s */" % entry_infos) - + entry_declaration = slave_variables.get((index, subindex), None) if entry_declaration is not None and not entry_declaration["mapped"]: pdo_needed = True - - entry_infos.update(dict(zip(["var_type", "dir", "var_name", "no_decl", "extra_declarations"], + + entry_infos.update(dict(zip(["var_type", "dir", "var_name", "no_decl", "extra_declarations"], entry_declaration["infos"]))) entry_declaration["mapped"] = True - + entry_type = entry.getDataType().getcontent() if entry_infos["var_type"] != entry_type: message = _("Wrong type for location \"%s\"!") % entry_infos["var_name"] - if (self.Controler.GetSizeOfType(entry_infos["var_type"]) != + if (self.Controler.GetSizeOfType(entry_infos["var_type"]) != self.Controler.GetSizeOfType(entry_type)): raise ValueError, message else: self.Controler.GetCTRoot().logger.write_warning(_("Warning: ") + message + "\n") - - if (entry_infos["dir"] == "I" and pdo_type != "Inputs" or + + if (entry_infos["dir"] == "I" and pdo_type != "Inputs" or entry_infos["dir"] == "Q" and pdo_type != "Outputs"): raise ValueError, _("Wrong direction for location \"%s\"!") % entry_infos["var_name"] - + ConfigureVariable(entry_infos, str_completion) - + elif pdo_type == "Outputs" and entry.getDataType() is not None and device_coe is not None: data_type = entry.getDataType().getcontent() entry_infos["dir"] = "Q" @@ -407,18 +407,18 @@ entry_infos["data_type"] = DATATYPECONVERSION.get(data_type) entry_infos["var_type"] = data_type entry_infos["real_var"] = "slave%(slave)d_%(index).4x_%(subindex).2x_default" % entry_infos - + ConfigureVariable(entry_infos, str_completion) - + str_completion["slaves_output_pdos_default_values_extraction"] += \ SLAVE_OUTPUT_PDO_DEFAULT_VALUE % entry_infos - + if pdo_needed: for excluded in pdo.getExclude(): excluded_index = ExtractHexDecValue(excluded.getcontent()) if excluded_index not in excluded_pdos: excluded_pdos.append(excluded_index) - + sm = pdo.getSm() if sm is None: for sm_idx, sync_manager in enumerate(sync_managers): @@ -426,40 +426,40 @@ sm = sm_idx if sm is None: raise ValueError, _("No sync manager available for %s pdo!") % pdo_type - + sync_managers[sm]["pdos_number"] += 1 sync_managers[sm]["pdos"].append( {"slave": slave_idx, "index": pdo_index, "name": ExtractName(pdo.getName()), - "type": pdo_type, + "type": pdo_type, "entries": entries_infos, "entries_number": len(entries_infos), "fixed": pdo.getFixed() == True}) - + if PdoConfig and PdoAssign: dynamic_pdos = {} dynamic_pdos_number = 0 - for category, min_index, max_index in [("Inputs", 0x1600, 0x1800), + for category, min_index, max_index in [("Inputs", 0x1600, 0x1800), ("Outputs", 0x1a00, 0x1C00)]: for sync_manager in sync_managers: if sync_manager["name"] == category: category_infos = dynamic_pdos.setdefault(category, {}) category_infos["sync_manager"] = sync_manager - category_infos["pdos"] = [pdo for pdo in category_infos["sync_manager"]["pdos"] + category_infos["pdos"] = [pdo for pdo in category_infos["sync_manager"]["pdos"] if not pdo["fixed"] and pdo["type"] == category] category_infos["current_index"] = min_index category_infos["max_index"] = max_index break - + for (index, subindex), entry_declaration in slave_variables.iteritems(): - + if not entry_declaration["mapped"]: entry = device_entries.get((index, subindex), None) if entry is None: raise ValueError, _("Unknown entry index 0x%4.4x, subindex 0x%2.2x for device %s") % \ (index, subindex, type_infos["device_type"]) - + entry_infos = { "index": index, "subindex": subindex, @@ -467,31 +467,31 @@ "bitlen": entry["BitSize"], } entry_infos.update(type_infos) - - entry_infos.update(dict(zip(["var_type", "dir", "var_name", "no_decl", "extra_declarations"], + + entry_infos.update(dict(zip(["var_type", "dir", "var_name", "no_decl", "extra_declarations"], entry_declaration["infos"]))) entry_declaration["mapped"] = True - + if entry_infos["var_type"] != entry["Type"]: message = _("Wrong type for location \"%s\"!") % entry_infos["var_name"] - if (self.Controler.GetSizeOfType(entry_infos["var_type"]) != + if (self.Controler.GetSizeOfType(entry_infos["var_type"]) != self.Controler.GetSizeOfType(entry["Type"])): raise ValueError, message else: self.Controler.GetCTRoot().logger.write_warning(message + "\n") - + if entry_infos["dir"] == "I" and entry["PDOMapping"] in ["T", "RT"]: pdo_type = "Inputs" elif entry_infos["dir"] == "Q" and entry["PDOMapping"] in ["R", "RT"]: pdo_type = "Outputs" else: raise ValueError, _("Wrong direction for location \"%s\"!") % entry_infos["var_name"] - + if not dynamic_pdos.has_key(pdo_type): raise ValueError, _("No Sync manager defined for %s!") % pdo_type - + ConfigureVariable(entry_infos, str_completion) - + if len(dynamic_pdos[pdo_type]["pdos"]) > 0: pdo = dynamic_pdos[pdo_type]["pdos"][0] elif module_extra_params["add_pdo"]: @@ -500,12 +500,12 @@ if dynamic_pdos[pdo_type]["current_index"] >= dynamic_pdos[pdo_type]["max_index"]: raise ValueError, _("No more free PDO index available for %s!") % pdo_type pdos_index.append(dynamic_pdos[pdo_type]["current_index"]) - + dynamic_pdos_number += 1 pdo = {"slave": slave_idx, "index": dynamic_pdos[pdo_type]["current_index"], "name": "Dynamic PDO %d" % dynamic_pdos_number, - "type": pdo_type, + "type": pdo_type, "entries": [], "entries_number": 0, "fixed": False} @@ -514,55 +514,55 @@ dynamic_pdos[pdo_type]["pdos"].append(pdo) else: break - + pdo["entries"].append(" {0x%(index).4x, 0x%(subindex).2x, %(bitlen)d}, /* %(name)s */" % entry_infos) if entry_infos["bitlen"] < module_extra_params["pdo_alignment"]: pdo["entries"].append(" {0x0000, 0x00, %d}, /* None */" % ( module_extra_params["pdo_alignment"] - entry_infos["bitlen"])) pdo["entries_number"] += 1 - + if pdo["entries_number"] == module_extra_params["max_pdo_size"]: dynamic_pdos[pdo_type]["pdos"].pop(0) - + pdo_offset = 0 entry_offset = 0 for sync_manager_infos in sync_managers: - + for pdo_infos in sync_manager_infos["pdos"]: pdo_infos["offset"] = entry_offset pdo_entries = pdo_infos["entries"] pdos_infos["pdos_infos"].append( - (" {0x%(index).4x, %(entries_number)d, " + + (" {0x%(index).4x, %(entries_number)d, " + "slave_%(slave)d_pdo_entries + %(offset)d}, /* %(name)s */") % pdo_infos) entry_offset += len(pdo_entries) pdos_infos["pdos_entries_infos"].extend(pdo_entries) - + sync_manager_infos["offset"] = pdo_offset pdo_offset_shift = sync_manager_infos["pdos_number"] pdos_infos["pdos_sync_infos"].append( - (" {%(index)d, %(sync_manager_type)s, %(pdos_number)d, " + + (" {%(index)d, %(sync_manager_type)s, %(pdos_number)d, " + ("slave_%(slave)d_pdos + %(offset)d" if pdo_offset_shift else "NULL") + ", %(watchdog)s},") % sync_manager_infos) - pdo_offset += pdo_offset_shift - + pdo_offset += pdo_offset_shift + for element in ["pdos_entries_infos", "pdos_infos", "pdos_sync_infos"]: pdos_infos[element] = "\n".join(pdos_infos[element]) - + str_completion["pdos_configuration_declaration"] += SLAVE_PDOS_CONFIGURATION_DECLARATION % pdos_infos - + for (index, subindex), entry_declaration in slave_variables.iteritems(): if not entry_declaration["mapped"]: message = _("Entry index 0x%4.4x, subindex 0x%2.2x not mapped for device %s") % \ (index, subindex, type_infos["device_type"]) self.Controler.GetCTRoot().logger.write_warning(_("Warning: ") + message + "\n") - - for element in ["used_pdo_entry_offset_variables_declaration", - "used_pdo_entry_configuration", - "located_variables_declaration", - "retrieve_variables", + + for element in ["used_pdo_entry_offset_variables_declaration", + "used_pdo_entry_configuration", + "located_variables_declaration", + "retrieve_variables", "publish_variables"]: str_completion[element] = "\n".join(str_completion[element]) - + etherlabfile = open(filepath, 'w') etherlabfile.write(plc_etherlab_code % str_completion) etherlabfile.close() diff -r 9460872f1440 -r fec77f2b9e07 etherlab/EthercatCIA402Slave.py --- a/etherlab/EthercatCIA402Slave.py Fri Sep 28 17:15:53 2018 +0300 +++ b/etherlab/EthercatCIA402Slave.py Fri Sep 28 17:20:11 2018 +0300 @@ -20,7 +20,7 @@ from ConfigEditor import CIA402NodeEditor # Definition of node variables that have to be mapped in PDO -# [(name, index, subindex, type, +# [(name, index, subindex, type, # direction for master ('I': input, 'Q': output)),...] NODE_VARIABLES = [ ("ControlWord", 0x6040, 0x00, "UINT", "Q"), @@ -38,12 +38,12 @@ # Definition of optional node variables that can be added to PDO mapping. # A checkbox will be displayed for each section in node configuration panel to # enable them -# [(section_name, -# [{'description', (name, index, subindex, type, +# [(section_name, +# [{'description', (name, index, subindex, type, # direction for master ('I': input, 'Q': output)), -# 'retrieve', string_template_for_retrieve_variable (None: not retrieved, +# 'retrieve', string_template_for_retrieve_variable (None: not retrieved, # default string template if not defined), -# 'publish', string_template_for_publish_variable (None: not published, +# 'publish', string_template_for_publish_variable (None: not published, # default string template if not defined), # },...] EXTRA_NODE_VARIABLES = [ @@ -74,16 +74,16 @@ # List of parameters name in no configuration panel for optional variable # sections EXTRA_NODE_VARIABLES_DICT = { - "Enable" + name: params + "Enable" + name: params for name, params in EXTRA_NODE_VARIABLES} # List of block to define to interface MCL to fieldbus for specific functions FIELDBUS_INTERFACE_GLOBAL_INSTANCES = [ - {"blocktype": "GetTorqueLimit", + {"blocktype": "GetTorqueLimit", "inputs": [], "outputs": [{"name": "TorqueLimitPos", "type": "UINT"}, {"name": "TorqueLimitNeg", "type": "UINT"}]}, - {"blocktype": "SetTorqueLimit", + {"blocktype": "SetTorqueLimit", "inputs": [{"name": "TorqueLimitPos", "type": "UINT"}, {"name": "TorqueLimitNeg", "type": "UINT"}], "outputs": []}, @@ -104,12 +104,12 @@ """ % ("\n".join(["""\ """ % category + use="optional" default="false"/>""" % category for category, variables in EXTRA_NODE_VARIABLES]) + AxisXSD) - + NODE_PROFILE = 402 EditorType = CIA402NodeEditor - + ConfNodeMethods = [ {"bitmap" : "CIA402AxisRef", "name" : _("Axis Ref"), @@ -122,25 +122,25 @@ "method" : "_getCIA402NetworkPosition", "push": True}, ] - + #-------------------------------------------------- # class code -#-------------------------------------------------- - +#-------------------------------------------------- + def __init__(self): # ----------- call ethercat mng. function -------------- self.CommonMethod = _CommonSlave(self) - + def GetIconName(self): return "CIA402Slave" - + def SetParamsAttribute(self, path, value): if path == "CIA402SlaveParams.Type": path = "SlaveParams.Type" elif path == "CIA402SlaveParams.Alias": path = "SlaveParams.Alias" return _EthercatSlaveCTN.SetParamsAttribute(self, path, value) - + def GetVariableLocationTree(self): axis_name = self.CTNName() current_location = self.GetCurrentLocation() @@ -163,44 +163,44 @@ "location": self.GetFullIEC_Channel(), "children": children, } - + def CTNGlobalInstances(self): current_location = self.GetCurrentLocation() - return [("%s_%s" % (block_infos["blocktype"], + return [("%s_%s" % (block_infos["blocktype"], "_".join(map(str, current_location))), - "EtherLab%s" % block_infos["blocktype"], "") + "EtherLab%s" % block_infos["blocktype"], "") for block_infos in FIELDBUS_INTERFACE_GLOBAL_INSTANCES] - + def StartDragNDrop(self, data): data_obj = wx.TextDataObject(str(data)) dragSource = wx.DropSource(self.GetCTRoot().AppFrame) dragSource.SetData(data_obj) dragSource.DoDragDrop() - + def _getCIA402NetworkPosition(self): self.StartDragNDrop( - ("%%IW%s" % ".".join(map(str, self.GetCurrentLocation())), + ("%%IW%s" % ".".join(map(str, self.GetCurrentLocation())), "location", "UINT", self.CTNName() + "_Pos", "")) - + def _getCIA402AxisRef(self): self.StartDragNDrop( - ("%%IW%s.402" % ".".join(map(str, self.GetCurrentLocation())), + ("%%IW%s.402" % ".".join(map(str, self.GetCurrentLocation())), "location", "AXIS_REF", self.CTNName(), "")) - + def CTNGenerate_C(self, buildpath, locations): current_location = self.GetCurrentLocation() - + location_str = "_".join(map(lambda x:str(x), current_location)) slave_pos = self.GetSlavePos() MCL_headers = Headers - - # Open CIA402 node code template file - plc_cia402node_filepath = os.path.join(os.path.split(__file__)[0], + + # Open CIA402 node code template file + plc_cia402node_filepath = os.path.join(os.path.split(__file__)[0], "plc_cia402node.c") plc_cia402node_file = open(plc_cia402node_filepath, 'r') plc_cia402node_code = plc_cia402node_file.read() plc_cia402node_file.close() - + # Init list of generated strings for each code template file section fieldbus_interface_declaration = [] fieldbus_interface_definition = [] @@ -210,31 +210,31 @@ extern_located_variables_declaration = [] entry_variables = [] init_entry_variables = [] - + # Fieldbus interface code sections for blocktype_infos in FIELDBUS_INTERFACE_GLOBAL_INSTANCES: blocktype = blocktype_infos["blocktype"] ucase_blocktype = blocktype.upper() blockname = "_".join([ucase_blocktype, location_str]) - + extract_inputs = "\n".join(["""\ __SET_VAR(%s->, %s,, %s);""" % (blockname, input_name, input_value) for (input_name, input_value) in [ ("EXECUTE", "__GET_VAR(data__->EXECUTE)")] + [ - (input["name"].upper(), + (input["name"].upper(), "__GET_VAR(data__->%s)" % input["name"].upper()) for input in blocktype_infos["inputs"]] ]) - - + + return_outputs = "\n".join(["""\ - __SET_VAR(data__->,%(output_name)s,, + __SET_VAR(data__->,%(output_name)s,, __GET_VAR(%(blockname)s->%(output_name)s));""" % locals() for output_name in ["DONE", "BUSY", "ERROR"] + [ output["name"].upper() for output in blocktype_infos["outputs"]] ]) - + fieldbus_interface_declaration.append(""" extern void ETHERLAB%(ucase_blocktype)s_body__(ETHERLAB%(ucase_blocktype)s* data__); void __%(blocktype)s_%(location_str)s(MC_%(ucase_blocktype)s *data__) { @@ -245,88 +245,88 @@ ETHERLAB%(ucase_blocktype)s_body__(%(blockname)s); %(return_outputs)s }""" % locals()) - + fieldbus_interface_definition.append("""\ AxsPub.axis->__mcl_func_MC_%(blocktype)s = __%(blocktype)s_%(location_str)s;\ """ % locals()) - + # Get a copy list of default variables to map variables = NODE_VARIABLES[:] - + # Set AxisRef public struct members value node_params = self.CTNParams[1].getElementInfos(self.CTNParams[0]) for param in node_params["children"]: param_name = param["name"] - + # Param is optional variables section enable flag extra_node_variable_infos = EXTRA_NODE_VARIABLES_DICT.get(param_name) if extra_node_variable_infos is not None: param_name = param_name.replace("Enable", "") + "Enabled" - + if not param["value"]: continue - + # Optional variables section is enabled for variable_infos in extra_node_variable_infos: var_name = variable_infos["description"][0] - + # Add each variables defined in section description to the # list of variables to map variables.append(variable_infos["description"]) - + # Add code to publish or retrive variable for var_exchange_dir, str_list, default_template in [ ("retrieve", extra_variables_retrieve, " AxsPub.axis->%(var_name)s = *(AxsPub.%(var_name)s);"), ("publish", extra_variables_publish, " *(AxsPub.%(var_name)s) = AxsPub.axis->%(var_name)s;")]: - - template = variable_infos.get(var_exchange_dir, + + template = variable_infos.get(var_exchange_dir, default_template) if template is not None: extra_variables_publish.append(template % locals()) - + # Set AxisRef public struct member value if defined if param["value"] is not None: param_value = ({True: "1", False: "0"}[param["value"]] if param["type"] == "boolean" else str(param["value"])) - + init_axis_params.append("""\ AxsPub.axis->%(param_name)s = %(param_value)s;""" % locals()) - + # Add each variable in list of variables to map to master list of # variables to add to network configuration for name, index, subindex, var_type, dir in variables: var_size = self.GetSizeOfType(var_type) var_name = """\ __%(dir)s%(var_size)s%(location_str)s_%(index)d_%(subindex)d""" % locals() - + extern_located_variables_declaration.append( "IEC_%(var_type)s *%(var_name)s;" % locals()) entry_variables.append( " IEC_%(var_type)s *%(name)s;" % locals()) init_entry_variables.append( " AxsPub.%(name)s = %(var_name)s;" % locals()) - + self.CTNParent.FileGenerator.DeclareVariable( slave_pos, index, subindex, var_type, dir, var_name) - + # Add newline between string in list of generated strings for sections [fieldbus_interface_declaration, fieldbus_interface_definition, init_axis_params, extra_variables_retrieve, extra_variables_publish, - extern_located_variables_declaration, entry_variables, + extern_located_variables_declaration, entry_variables, init_entry_variables] = map(lambda l: "\n".join(l), [ fieldbus_interface_declaration, fieldbus_interface_definition, init_axis_params, extra_variables_retrieve, extra_variables_publish, - extern_located_variables_declaration, entry_variables, + extern_located_variables_declaration, entry_variables, init_entry_variables]) - + # Write generated content to CIA402 node file - Gen_CIA402Nodefile_path = os.path.join(buildpath, + Gen_CIA402Nodefile_path = os.path.join(buildpath, "cia402node_%s.c"%location_str) cia402nodefile = open(Gen_CIA402Nodefile_path, 'w') cia402nodefile.write(plc_cia402node_code % locals()) cia402nodefile.close() - + return [(Gen_CIA402Nodefile_path, '"-I%s"'%os.path.abspath(self.GetCTRoot().GetIECLibPath()))],"",True diff -r 9460872f1440 -r fec77f2b9e07 etherlab/EthercatMaster.py --- a/etherlab/EthercatMaster.py Fri Sep 28 17:15:53 2018 +0300 +++ b/etherlab/EthercatMaster.py Fri Sep 28 17:20:11 2018 +0300 @@ -79,21 +79,21 @@ etherlab_ext_file = open(GetLocalPath("etherlab_ext.c"), 'r') etherlab_ext_code = etherlab_ext_file.read() etherlab_ext_file.close() - + Gen_etherlabfile_path = os.path.join(buildpath, "etherlab_ext.c") ethelabfile = open(Gen_etherlabfile_path,'w') ethelabfile.write(etherlab_ext_code) ethelabfile.close() - + runtimefile_path = os.path.join(os.path.split(__file__)[0], "runtime_etherlab.py") - return ((["etherlab_ext"], [(Gen_etherlabfile_path, IECCFLAGS)], True), "", + return ((["etherlab_ext"], [(Gen_etherlabfile_path, IECCFLAGS)], True), "", ("runtime_etherlab.py", file(GetLocalPath("runtime_etherlab.py")))) - + #-------------------------------------------------- # Ethercat MASTER #-------------------------------------------------- -EtherCATConfigParser = GenerateParserFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATConfig.xsd")) +EtherCATConfigParser = GenerateParserFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATConfig.xsd")) def sort_commands(x, y): if x["Index"] == y["Index"]: @@ -102,7 +102,7 @@ cls = EtherCATConfigParser.GetElementClass("Slave", "Config") if cls: - + def getType(self): slave_info = self.getInfo() return {"device_type": slave_info.getName(), @@ -118,7 +118,7 @@ slave_info.setProductCode(ExtractHexDecValue(type_infos["product_code"])) slave_info.setRevisionNo(ExtractHexDecValue(type_infos["revision_number"])) setattr(cls, "setType", setType) - + def getInitCmds(self, create_default=False): Mailbox = self.getMailbox() if Mailbox is None: @@ -140,7 +140,7 @@ InitCmds = CoE.getInitCmds() return InitCmds setattr(cls, "getInitCmds", getInitCmds) - + def getStartupCommands(self): pos = self.getInfo().getPhysAddr() InitCmds = self.getInitCmds() @@ -161,7 +161,7 @@ commands.sort(sort_commands) return commands setattr(cls, "getStartupCommands", getStartupCommands) - + def appendStartupCommand(self, command_infos): InitCmds = self.getInitCmds(True) command = EtherCATConfigParser.CreateElement("InitCmd", "InitCmds", 1) @@ -172,7 +172,7 @@ command.setComment(command_infos["Description"]) return len(InitCmds.getInitCmd()) - 1 setattr(cls, "appendStartupCommand", appendStartupCommand) - + def setStartupCommand(self, command_infos): InitCmds = self.getInitCmds() if InitCmds is not None: @@ -184,7 +184,7 @@ command.setData(command_infos["Value"]) command.setComment(command_infos["Description"]) setattr(cls, "setStartupCommand", setStartupCommand) - + def removeStartupCommand(self, command_idx): InitCmds = self.getInitCmds() if InitCmds is not None: @@ -218,7 +218,7 @@ """ -ProcessVariablesParser = GenerateParserFromXSDstring(ProcessVariablesXSD) +ProcessVariablesParser = GenerateParserFromXSDstring(ProcessVariablesXSD) class _EthercatCTN: @@ -226,7 +226,7 @@ if HAS_MCL: CTNChildrenTypes.append(("EthercatCIA402Slave", _EthercatCIA402SlaveCTN, "Ethercat CIA402 Slave")) EditorType = MasterEditor - + def __init__(self): config_filepath = self.ConfigFileName() config_is_saved = False @@ -241,14 +241,14 @@ except Exception, e: error = e.message config_xmlfile.close() - + if error is not None: self.GetCTRoot().logger.write_error( - _("Couldn't load %s network configuration file.") % CTNName) - + _("Couldn't load %s network configuration file.") % CTNName) + if self.Config is None: self.Config = EtherCATConfigParser.CreateElement("EtherCATConfig") - + process_filepath = self.ProcessVariablesFileName() process_is_saved = False self.ProcessVariables = None @@ -262,32 +262,32 @@ except Exception, e: error = e.message process_xmlfile.close() - + if error is not None: self.GetCTRoot().logger.write_error( - _("Couldn't load %s network process variables file.") % CTNName) - + _("Couldn't load %s network process variables file.") % CTNName) + if self.ProcessVariables is None: self.ProcessVariables = ProcessVariablesParser.CreateElement("ProcessVariables") - + if config_is_saved and process_is_saved: self.CreateBuffer(True) else: self.CreateBuffer(False) self.OnCTNSave() - + # ----------- call ethercat mng. function -------------- self.CommonMethod = _CommonSlave(self) - + def GetIconName(self): return "Ethercat" - + def GetContextualMenuItems(self): return [("Add Ethercat Slave", "Add Ethercat Slave to Master", self.OnAddEthercatSlave)] - + def OnAddEthercatSlave(self, event): app_frame = self.GetCTRoot().AppFrame - dialog = BrowseValuesLibraryDialog(app_frame, + dialog = BrowseValuesLibraryDialog(app_frame, "Ethercat Slave Type", self.GetSlaveTypesLibrary()) if dialog.ShowModal() == wx.ID_OK: type_infos = dialog.GetValueInfos() @@ -303,7 +303,7 @@ new_child._OpenView() app_frame._Refresh(TITLE, FILEMENU, PROJECTTREE) dialog.Destroy() - + def ExtractHexDecValue(self, value): return ExtractHexDecValue(value) @@ -312,10 +312,10 @@ def ConfigFileName(self): return os.path.join(self.CTNPath(), "config.xml") - + def ProcessVariablesFileName(self): return os.path.join(self.CTNPath(), "process_variables.xml") - + def FilterSlave(self, slave, vendor=None, slave_pos=None, slave_profile=None): if slave_pos is not None and slave.getInfo().getPhysAddr() != slave_pos: return False @@ -355,7 +355,7 @@ commands.append((slave.getInfo().getPhysAddr(), slave.getStartupCommands())) commands.sort() return reduce(lambda x, y: x + y[1], commands, []) - + def AppendStartupCommand(self, command_infos): slave = self.GetSlave(command_infos["Position"]) if slave is not None: @@ -363,20 +363,20 @@ self.BufferModel() return command_idx return None - + def SetStartupCommandInfos(self, command_infos): slave = self.GetSlave(command_infos["Position"]) if slave is not None: slave.setStartupCommand(command_infos) self.BufferModel() - + def RemoveStartupCommand(self, slave_pos, command_idx, buffer=True): slave = self.GetSlave(slave_pos) if slave is not None: slave.removeStartupCommand(command_idx) if buffer: self.BufferModel() - + def SetProcessVariables(self, variables): vars = [] for var in variables: @@ -406,7 +406,7 @@ vars.append(variable) self.ProcessVariables.setvariable(vars) self.BufferModel() - + def GetProcessVariables(self): variables = [] idx = 0 @@ -431,19 +431,19 @@ variables.append(var) idx += 1 return variables - + def _ScanNetwork(self): app_frame = self.GetCTRoot().AppFrame - + execute = True if len(self.Children) > 0: - dialog = wx.MessageDialog(app_frame, - _("The current network configuration will be deleted.\nDo you want to continue?"), - _("Scan Network"), + dialog = wx.MessageDialog(app_frame, + _("The current network configuration will be deleted.\nDo you want to continue?"), + _("Scan Network"), wx.YES_NO|wx.ICON_QUESTION) execute = dialog.ShowModal() == wx.ID_YES dialog.Destroy() - + if execute: error, returnVal = self.RemoteExec(SCAN_COMMAND, returnVal = None) if error != 0: @@ -453,7 +453,7 @@ elif returnVal is not None: for child in self.IECSortedChildren(): self._doRemoveChild(child) - + for slave in returnVal: type_infos = { "vendor": slave["vendor_id"], @@ -470,10 +470,10 @@ self.SetSlaveAlias(slave["idx"], slave["alias"]) type_infos["device_type"] = device.getType().getcontent() self.SetSlaveType(slave["idx"], type_infos) - + if app_frame: app_frame.RefreshProjectTree() - + def CTNAddChild(self, CTNName, CTNType, IEC_Channel=0): """ Create the confnodes that may be added as child to this node self @@ -481,7 +481,7 @@ @param CTNName: string for the name of the confnode instance """ newConfNodeOpj = ConfigTreeNode.CTNAddChild(self, CTNName, CTNType, IEC_Channel) - + slave = self.GetSlave(newConfNodeOpj.BaseParams.getIEC_Channel()) if slave is None: slave = EtherCATConfigParser.CreateElement("Slave", "Config") @@ -492,7 +492,7 @@ slave_infos.setAutoIncAddr(0) self.BufferModel() self.OnCTNSave() - + return newConfNodeOpj def _doRemoveChild(self, CTNInstance): @@ -523,33 +523,33 @@ if self._View is not None: self._View.RefreshView() self._View.RefreshBuffer() - + def GetSlaveAlias(self, slave_pos): slave = self.GetSlave(slave_pos) if slave is not None: slave_info = slave.getInfo() return slave_info.getAutoIncAddr() return None - + def SetSlaveAlias(self, slave_pos, alias): slave = self.GetSlave(slave_pos) if slave is not None: slave_info = slave.getInfo() slave_info.setAutoIncAddr(alias) self.BufferModel() - + def GetSlaveType(self, slave_pos): slave = self.GetSlave(slave_pos) if slave is not None: return slave.getType() return None - + def SetSlaveType(self, slave_pos, type_infos): slave = self.GetSlave(slave_pos) if slave is not None: slave.setType(type_infos) self.BufferModel() - + def GetSlaveInfos(self, slave_pos): slave = self.GetSlave(slave_pos) if slave is not None: @@ -562,7 +562,7 @@ "entries": self.GetSlaveVariables(device)}) return infos return None - + def GetSlaveVariables(self, slave_pos=None, limits=None, device=None): if device is None and slave_pos is not None: slave = self.GetSlave(slave_pos) @@ -592,7 +592,7 @@ entries.append(entry) return entries return [] - + def GetSlaveVariableDataType(self, slave_pos, index, subindex): slave = self.GetSlave(slave_pos) if slave is not None: @@ -603,7 +603,7 @@ if entry_infos is not None: return entry_infos["Type"] return None - + def GetNodesVariables(self, vendor=None, slave_pos=None, slave_profile=None, limits=None): entries = [] for slave_position in self.GetSlaves(): @@ -618,22 +618,22 @@ continue entries.extend(self.GetSlaveVariables(slave_position, limits, device)) return entries - + def GetModuleInfos(self, type_infos): return self.CTNParent.GetModuleInfos(type_infos) - + def GetSlaveTypesLibrary(self, profile_filter=None): return self.CTNParent.GetModulesLibrary(profile_filter) - + def GetLibraryVendors(self): return self.CTNParent.GetVendors() - + def GetDeviceLocationTree(self, slave_pos, current_location, device_name): slave = self.GetSlave(slave_pos) - vars = [] + vars = [] if slave is not None: type_infos = slave.getType() - + device, module_extra_params = self.GetModuleInfos(type_infos) if device is not None: sync_managers = [] @@ -644,7 +644,7 @@ sync_managers.append(LOCATION_VAR_OUTPUT) else: sync_managers.append(LOCATION_VAR_INPUT) - + entries = device.GetEntriesList().items() entries.sort() for (index, subindex), entry in entries: @@ -655,44 +655,44 @@ if var_class == LOCATION_VAR_INPUT: var_dir = "%I" else: - var_dir = "%Q" - + var_dir = "%Q" + vars.append({"name": "0x%4.4x-0x%2.2x: %s" % (index, subindex, entry["Name"]), "type": var_class, "size": var_size, "IEC_type": entry["Type"], "var_name": "%s_%4.4x_%2.2x" % ("_".join(device_name.split()), index, subindex), - "location": "%s%s%s"%(var_dir, var_size, ".".join(map(str, current_location + + "location": "%s%s%s"%(var_dir, var_size, ".".join(map(str, current_location + (index, subindex)))), "description": "", "children": []}) - + return vars - + def CTNTestModified(self): - return self.ChangesToSave or not self.ModelIsSaved() + return self.ChangesToSave or not self.ModelIsSaved() def OnCTNSave(self, from_project_path=None): config_filepath = self.ConfigFileName() - + config_xmlfile = open(config_filepath,"w") config_xmlfile.write(etree.tostring( - self.Config, - pretty_print=True, - xml_declaration=True, + self.Config, + pretty_print=True, + xml_declaration=True, encoding='utf-8')) config_xmlfile.close() - + process_filepath = self.ProcessVariablesFileName() - + process_xmlfile = open(process_filepath,"w") process_xmlfile.write(etree.tostring( - self.ProcessVariables, - pretty_print=True, - xml_declaration=True, + self.ProcessVariables, + pretty_print=True, + xml_declaration=True, encoding='utf-8')) process_xmlfile.close() - + self.Buffer.CurrentSaved() return True @@ -703,13 +703,13 @@ current_location = self.GetCurrentLocation() # define a unique name for the generated C file location_str = "_".join(map(lambda x:str(x), current_location)) - + Gen_Ethercatfile_path = os.path.join(buildpath, "ethercat_%s.c"%location_str) - + self.FileGenerator = _EthercatCFileGenerator(self) - + LocationCFilesAndCFLAGS, LDFLAGS, extra_files = ConfigTreeNode._Generate_C(self, buildpath, locations) - + for idx, variable in enumerate(self.ProcessVariables.getvariable()): name = None var_type = None @@ -734,42 +734,42 @@ name = self.GetProcessVariableName(location, var_type) self.FileGenerator.DeclareVariable( pos, index, subindex, var_type, "Q", name, True) - + self.FileGenerator.GenerateCFile(Gen_Ethercatfile_path, location_str, self.BaseParams.getIEC_Channel()) - - LocationCFilesAndCFLAGS.insert(0, - (current_location, - [(Gen_Ethercatfile_path, '"-I%s"'%os.path.abspath(self.GetCTRoot().GetIECLibPath()))], + + LocationCFilesAndCFLAGS.insert(0, + (current_location, + [(Gen_Ethercatfile_path, '"-I%s"'%os.path.abspath(self.GetCTRoot().GetIECLibPath()))], True)) LDFLAGS.append("-lethercat_rtdm -lrtdm") - + return LocationCFilesAndCFLAGS, LDFLAGS, extra_files ConfNodeMethods = [ {"bitmap" : "ScanNetwork", - "name" : _("Scan Network"), + "name" : _("Scan Network"), "tooltip" : _("Scan Network"), "method" : "_ScanNetwork"}, ] def CTNGenerate_C(self, buildpath, locations): current_location = self.GetCurrentLocation() - + slaves = self.GetSlaves() for slave_pos in slaves: slave = self.GetSlave(slave_pos) if slave is not None: self.FileGenerator.DeclareSlave(slave_pos, slave) - + for location in locations: loc = location["LOC"][len(current_location):] slave_pos = loc[0] if slave_pos in slaves and len(loc) == 3 and location["DIR"] != "M": self.FileGenerator.DeclareVariable( slave_pos, loc[1], loc[2], location["IEC_TYPE"], location["DIR"], location["NAME"]) - + return [],"",False - + #------------------------------------------------------------------------------- # Current Buffering Management Functions #------------------------------------------------------------------------------- @@ -779,18 +779,18 @@ """ def Copy(self, model): return deepcopy(model) - + def CreateBuffer(self, saved): self.Buffer = UndoBuffer( - (EtherCATConfigParser.Dumps(self.Config), - ProcessVariablesParser.Dumps(self.ProcessVariables)), + (EtherCATConfigParser.Dumps(self.Config), + ProcessVariablesParser.Dumps(self.ProcessVariables)), saved) - + def BufferModel(self): self.Buffer.Buffering( - (EtherCATConfigParser.Dumps(self.Config), + (EtherCATConfigParser.Dumps(self.Config), ProcessVariablesParser.Dumps(self.ProcessVariables))) - + def ModelIsSaved(self): if self.Buffer is not None: return self.Buffer.IsCurrentSaved() @@ -801,14 +801,13 @@ config, process_variables = self.Buffer.Previous() self.Config = EtherCATConfigParser.Loads(config) self.ProcessVariables = ProcessVariablesParser.Loads(process_variables) - + def LoadNext(self): config, process_variables = self.Buffer.Next() self.Config = EtherCATConfigParser.Loads(config) self.ProcessVariables = ProcessVariablesParser.Loads(process_variables) - + def GetBufferState(self): first = self.Buffer.IsFirst() last = self.Buffer.IsLast() return not first, not last - diff -r 9460872f1440 -r fec77f2b9e07 etherlab/EthercatSlave.py --- a/etherlab/EthercatSlave.py Fri Sep 28 17:15:53 2018 +0300 +++ b/etherlab/EthercatSlave.py Fri Sep 28 17:20:11 2018 +0300 @@ -17,16 +17,16 @@ from ConfigEditor import NodeEditor #------------------------------------------ -from CommonEtherCATFunction import _CommonSlave +from CommonEtherCATFunction import _CommonSlave #------------------------------------------ TYPECONVERSION = {"BOOL" : "X", "SINT" : "B", "INT" : "W", "DINT" : "D", "LINT" : "L", - "USINT" : "B", "UINT" : "W", "UDINT" : "D", "ULINT" : "L", + "USINT" : "B", "UINT" : "W", "UDINT" : "D", "ULINT" : "L", "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L"} DATATYPECONVERSION = {"BOOL" : "BIT", "SINT" : "S8", "INT" : "S16", "DINT" : "S32", "LINT" : "S64", - "USINT" : "U8", "UINT" : "U16", "UDINT" : "U32", "ULINT" : "U64", + "USINT" : "U8", "UINT" : "U16", "UDINT" : "U32", "ULINT" : "U64", "BYTE" : "U8", "WORD" : "U16", "DWORD" : "U32", "LWORD" : "U64"} VARCLASSCONVERSION = {"T": LOCATION_VAR_INPUT, "R": LOCATION_VAR_OUTPUT, "RT": LOCATION_VAR_MEMORY} @@ -66,23 +66,23 @@ class _EthercatSlaveCTN: NODE_PROFILE = None EditorType = NodeEditor - + def __init__(self): # ----------- call ethercat mng. function -------------- self.CommonMethod = _CommonSlave(self) - + def GetIconName(self): return "Slave" - + def ExtractHexDecValue(self, value): return ExtractHexDecValue(value) - + def GetSizeOfType(self, type): return TYPECONVERSION.get(self.GetCTRoot().GetBaseType(type), None) - + def GetSlavePos(self): return self.BaseParams.getIEC_Channel() - + def GetParamsAttributes(self, path = None): if path: parts = path.split(".", 1) @@ -96,30 +96,30 @@ params.append(self.CTNParams[1].getElementInfos(self.CTNParams[0])) else: params.append({ - 'use': 'required', - 'type': 'element', - 'name': 'SlaveParams', - 'value': None, + 'use': 'required', + 'type': 'element', + 'name': 'SlaveParams', + 'value': None, 'children': [] }) - + slave_type = self.CTNParent.GetSlaveType(self.GetSlavePos()) params[0]['children'].insert(0, - {'use': 'optional', - 'type': self.CTNParent.GetSlaveTypesLibrary(self.NODE_PROFILE), - 'name': 'Type', - 'value': (slave_type["device_type"], slave_type)}) + {'use': 'optional', + 'type': self.CTNParent.GetSlaveTypesLibrary(self.NODE_PROFILE), + 'name': 'Type', + 'value': (slave_type["device_type"], slave_type)}) params[0]['children'].insert(1, - {'use': 'optional', - 'type': 'unsignedLong', - 'name': 'Alias', + {'use': 'optional', + 'type': 'unsignedLong', + 'name': 'Alias', 'value': self.CTNParent.GetSlaveAlias(self.GetSlavePos())}) return params - + def SetParamsAttribute(self, path, value): self.GetSlaveInfos() position = self.BaseParams.getIEC_Channel() - + if path == "SlaveParams.Type": self.CTNParent.SetSlaveType(position, value) slave_type = self.CTNParent.GetSlaveType(self.GetSlavePos()) @@ -133,21 +133,21 @@ elif path == "SlaveParams.Alias": self.CTNParent.SetSlaveAlias(position, value) return value, True - + value, refresh = ConfigTreeNode.SetParamsAttribute(self, path, value) - + # Filter IEC_Channel, Slave_Type and Alias that have specific behavior if path == "BaseParams.IEC_Channel" and value != position: self.CTNParent.SetSlavePosition(position, value) - + return value, refresh - + def GetSlaveInfos(self): return self.CTNParent.GetSlaveInfos(self.GetSlavePos()) - + def GetSlaveVariables(self, limits): return self.CTNParent.GetSlaveVariables(self.GetSlavePos(), limits) - + def GetVariableLocationTree(self): return {"name": self.BaseParams.getName(), "type": LOCATION_CONFNODE, diff -r 9460872f1440 -r fec77f2b9e07 etherlab/etherlab.py --- a/etherlab/etherlab.py Fri Sep 28 17:15:53 2018 +0300 +++ b/etherlab/etherlab.py Fri Sep 28 17:20:11 2018 +0300 @@ -30,14 +30,14 @@ # Ethercat ConfNode #-------------------------------------------------- -EtherCATInfoParser = GenerateParserFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATInfo.xsd")) +EtherCATInfoParser = GenerateParserFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATInfo.xsd")) EtherCATInfo_XPath = lambda xpath: etree.XPath(xpath) def HexDecValue(context, *args): return str(ExtractHexDecValue(args[0][0])) def EntryName(context, *args): - return ExtractName(args[0], + return ExtractName(args[0], args[1][0] if len(args) > 1 else None) ENTRY_INFOS_KEYS = [ @@ -56,14 +56,14 @@ def __init__(self, entries): self.Entries = entries - + def AddEntry(self, context, *args): index, subindex = map(lambda x: int(x[0]), args[:2]) new_entry_infos = { key: translate(arg[0]) if len(arg) > 0 else default for (key, translate, default), arg in zip(ENTRY_INFOS_KEYS, args)} - + if (index, subindex) != (0, 0): entry_infos = self.Entries.get((index, subindex)) if entry_infos is not None: @@ -79,12 +79,12 @@ cls = EtherCATInfoParser.GetElementClass("DeviceType") if cls: - + profile_numbers_xpath = EtherCATInfo_XPath("Profile/ProfileNo") def GetProfileNumbers(self): return [number.text for number in profile_numbers_xpath(self)] setattr(cls, "GetProfileNumbers", GetProfileNumbers) - + def getCoE(self): mailbox = self.getMailbox() if mailbox is not None: @@ -94,20 +94,20 @@ def GetEntriesList(self, limits=None): entries = {} - + factory = EntryListFactory(entries) - + entries_list_xslt_tree = etree.XSLT( entries_list_xslt, extensions = { ("entries_list_ns", "AddEntry"): factory.AddEntry, ("entries_list_ns", "HexDecValue"): HexDecValue, ("entries_list_ns", "EntryName"): EntryName}) entries_list_xslt_tree(self, **dict(zip( - ["min_index", "max_index"], + ["min_index", "max_index"], map(lambda x: etree.XSLT.strparam(str(x)), limits if limits is not None else [0x0000, 0xFFFF]) ))) - + return entries setattr(cls, "GetEntriesList", GetEntriesList) @@ -147,7 +147,7 @@ MODULES_EXTRA_PARAMS = [ ("pdo_alignment", { - "column_label": _("PDO alignment"), + "column_label": _("PDO alignment"), "column_size": 150, "default": 8, "description": _( @@ -160,7 +160,7 @@ """Maximal number of entries mapped in a PDO including empty entries used for PDO alignment""")}), ("add_pdo", { - "column_label": _("Creating new PDO"), + "column_label": _("Creating new PDO"), "column_size": 150, "default": 0, "description": _( @@ -168,36 +168,36 @@ for mapping needed location variables (1 if possible)""")}) ] - + def __init__(self, path, parent_library=None): self.Path = path if not os.path.exists(self.Path): os.makedirs(self.Path) self.ParentLibrary = parent_library - + if parent_library is not None: self.LoadModules() else: self.Library = None self.LoadModulesExtraParams() - + def GetPath(self): return self.Path - + def GetModulesExtraParamsFilePath(self): return os.path.join(self.Path, "modules_extra_params.cfg") - + groups_xpath = EtherCATInfo_XPath("Descriptions/Groups/Group") devices_xpath = EtherCATInfo_XPath("Descriptions/Devices/Device") def LoadModules(self): self.Library = {} - + files = os.listdir(self.Path) for file in files: filepath = os.path.join(self.Path, file) if os.path.isfile(filepath) and os.path.splitext(filepath)[-1] == ".xml": self.modules_infos = None - + xmlfile = open(filepath, 'r') try: self.modules_infos, error = EtherCATInfoParser.LoadXMLString(xmlfile.read()) @@ -207,37 +207,37 @@ except Exception, exc: self.modules_infos, error = None, unicode(exc) xmlfile.close() - + if self.modules_infos is not None: vendor = self.modules_infos.getVendor() - + vendor_category = self.Library.setdefault( - ExtractHexDecValue(vendor.getId()), - {"name": ExtractName(vendor.getName(), _("Miscellaneous")), + ExtractHexDecValue(vendor.getId()), + {"name": ExtractName(vendor.getName(), _("Miscellaneous")), "groups": {}}) - + for group in self.groups_xpath(self.modules_infos): group_type = group.getType() - - vendor_category["groups"].setdefault(group_type, - {"name": ExtractName(group.getName(), group_type), + + vendor_category["groups"].setdefault(group_type, + {"name": ExtractName(group.getName(), group_type), "parent": group.getParentGroup(), - "order": group.getSortOrder(), + "order": group.getSortOrder(), #"value": group.getcontent()["value"], "devices": []}) - + for device in self.devices_xpath(self.modules_infos): device_group = device.getGroupType() if not vendor_category["groups"].has_key(device_group): raise ValueError, "Not such group \"%\"" % device_group vendor_category["groups"][device_group]["devices"].append( (device.getType().getcontent(), device)) - + else: - + self.GetCTRoot().logger.write_error( _("Couldn't load %s XML file:\n%s") % (filepath, error)) - + return self.Library def GetModulesLibrary(self, profile_filter=None): @@ -290,7 +290,7 @@ def GetVendors(self): return [(vendor_id, vendor["name"]) for vendor_id, vendor in self.Library.items()] - + def GetModuleInfos(self, module_infos): vendor = ExtractHexDecValue(module_infos["vendor"]) vendor_infos = self.Library.get(vendor) @@ -301,21 +301,21 @@ revision_number = ExtractHexDecValue(device_infos.getType().getRevisionNo()) if (product_code == ExtractHexDecValue(module_infos["product_code"]) and revision_number == ExtractHexDecValue(module_infos["revision_number"])): - self.cntdevice = device_infos - self.cntdeviceType = device_type + self.cntdevice = device_infos + self.cntdeviceType = device_type return device_infos, self.GetModuleExtraParams(vendor, product_code, revision_number) return None, None - + def ImportModuleLibrary(self, filepath): if os.path.isfile(filepath): shutil.copy(filepath, self.Path) self.LoadModules() return True return False - + def LoadModulesExtraParams(self): self.ModulesExtraParams = {} - + csvfile_path = self.GetModulesExtraParamsFilePath() if os.path.exists(csvfile_path): csvfile = open(csvfile_path, "rb") @@ -336,44 +336,44 @@ self.ModulesExtraParams[ tuple(map(int, row[:3]))] = params_values csvfile.close() - + def SaveModulesExtraParams(self): csvfile = open(self.GetModulesExtraParamsFilePath(), "wb") extra_params = [param for param, params_infos in self.MODULES_EXTRA_PARAMS] writer = csv.writer(csvfile, delimiter=';') writer.writerow(['Vendor', 'product_code', 'revision_number'] + extra_params) for (vendor, product_code, revision_number), module_extra_params in self.ModulesExtraParams.iteritems(): - writer.writerow([vendor, product_code, revision_number] + - [module_extra_params.get(param, '') + writer.writerow([vendor, product_code, revision_number] + + [module_extra_params.get(param, '') for param in extra_params]) csvfile.close() - + def SetModuleExtraParam(self, vendor, product_code, revision_number, param, value): vendor = ExtractHexDecValue(vendor) product_code = ExtractHexDecValue(product_code) revision_number = ExtractHexDecValue(revision_number) - + module_infos = (vendor, product_code, revision_number) self.ModulesExtraParams.setdefault(module_infos, {}) self.ModulesExtraParams[module_infos][param] = value - + self.SaveModulesExtraParams() - + def GetModuleExtraParams(self, vendor, product_code, revision_number): vendor = ExtractHexDecValue(vendor) product_code = ExtractHexDecValue(product_code) revision_number = ExtractHexDecValue(revision_number) - + if self.ParentLibrary is not None: extra_params = self.ParentLibrary.GetModuleExtraParams(vendor, product_code, revision_number) else: extra_params = {} - + extra_params.update(self.ModulesExtraParams.get((vendor, product_code, revision_number), {})) - + for param, param_infos in self.MODULES_EXTRA_PARAMS: extra_params.setdefault(param, param_infos["default"]) - + return extra_params USERDATA_DIR = wx.StandardPaths.Get().GetUserDataDir() @@ -384,50 +384,49 @@ os.path.join(USERDATA_DIR, "ethercat_modules")) class RootClass: - + CTNChildrenTypes = [("EthercatNode",_EthercatCTN,"Ethercat Master")] EditorType = LibraryEditor - - + + def __init__(self): self.ModulesLibrary = None self.LoadModulesLibrary() - + def GetIconName(self): return "Ethercat" - + def GetModulesLibraryPath(self, project_path=None): if project_path is None: project_path = self.CTNPath() - return os.path.join(project_path, "modules") - + return os.path.join(project_path, "modules") + def OnCTNSave(self, from_project_path=None): if from_project_path is not None: shutil.copytree(self.GetModulesLibraryPath(from_project_path), self.GetModulesLibraryPath()) return True - + def CTNGenerate_C(self, buildpath, locations): return [],"",False - + def LoadModulesLibrary(self): if self.ModulesLibrary is None: self.ModulesLibrary = ModulesLibrary(self.GetModulesLibraryPath(), ModulesDatabase) else: self.ModulesLibrary.LoadModulesLibrary() - + def GetModulesDatabaseInstance(self): return ModulesDatabase - + def GetModulesLibraryInstance(self): return self.ModulesLibrary - + def GetModulesLibrary(self, profile_filter=None): return self.ModulesLibrary.GetModulesLibrary(profile_filter) - + def GetVendors(self): return self.ModulesLibrary.GetVendors() - + def GetModuleInfos(self, module_infos): return self.ModulesLibrary.GetModuleInfos(module_infos) - diff -r 9460872f1440 -r fec77f2b9e07 etherlab/runtime_etherlab.py --- a/etherlab/runtime_etherlab.py Fri Sep 28 17:15:53 2018 +0300 +++ b/etherlab/runtime_etherlab.py Fri Sep 28 17:20:11 2018 +0300 @@ -17,12 +17,12 @@ cmdfmt = "ethercat upload -p %d -t %s 0x%.4x 0x%.2x" else: cmdfmt = "ethercat download -p %d -t %s 0x%.4x 0x%.2x %s" - + command = cmdfmt % params[1:] SDOProc = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) res = SDOProc.wait() output = SDOProc.communicate()[0] - + if params[0] == "upload": Result = None if res == 0: @@ -36,18 +36,18 @@ Result = int(dec_value) else: Result = res == 0 - + SDOAnswered() if res != 0 : PLCObject.LogMessage( - LogLevelsDict["WARNING"], + LogLevelsDict["WARNING"], "%s : %s"%(command,output)) - + def EthercatSDOUpload(pos, index, subindex, var_type): global SDOThread SDOThread = Thread(target=SDOThreadProc, args=["upload", pos, var_type, index, subindex]) SDOThread.start() - + def EthercatSDODownload(pos, index, subindex, var_type, value): global SDOThread SDOThread = Thread(target=SDOThreadProc, args=["download", pos, var_type, index, subindex, value]) @@ -63,7 +63,7 @@ """ Logs Kernel messages starting with EtherCAT Uses GLibc wrapper to Linux syscall "klogctl" - Last 4 KB are polled, and lines compared to last + Last 4 KB are polled, and lines compared to last captured line to detect new lines """ global StopKMSGThread @@ -78,7 +78,7 @@ log = s.value[:l-1] if last : log = log.rpartition(last)[2] - if log : + if log : last = log.rpartition('\n')[2] for lvl,msg in re.findall( r'<(\d)>\[\s*\d*\.\d*\]\s*(EtherCAT\s*.*)$', @@ -88,7 +88,7 @@ "4":"WARNING", "3":"CRITICAL"}.get(lvl,"DEBUG")], msg) - time.sleep(0.5) + time.sleep(0.5) def _runtime_etherlab_init(): global KMSGPollThread, StopKMSGThread @@ -105,4 +105,3 @@ SDOThread = None StopKMSGThread = True KMSGPollThread = None -