cleanup etherlab: pep8, W291 trailing whitespace
authorAndrey Skvortsov <andrej.skvortzov@gmail.com>
Fri, 28 Sep 2018 17:20:11 +0300
changeset 2355 fec77f2b9e07
parent 2354 9460872f1440
child 2356 c26e0c66d8d5
cleanup etherlab: pep8, W291 trailing whitespace
etherlab/CommonEtherCATFunction.py
etherlab/ConfigEditor.py
etherlab/EtherCATManagementEditor.py
etherlab/EthercatCFileGenerator.py
etherlab/EthercatCIA402Slave.py
etherlab/EthercatMaster.py
etherlab/EthercatSlave.py
etherlab/etherlab.py
etherlab/runtime_etherlab.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; <Device>-<Eeprom>-<ByteSize>
                 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; <Device>-<Eeprom>-<ConfigData> address 0x00
@@ -478,12 +478,12 @@
                 elif eeprom_element["name"] == "BootStrap":
                     bootstrap_data = "{:0>16x}".format(eeprom_element)
                     # get bootstrap configuration; <Device>-<Eeprom>-<BootStrap>
-                    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; <Device>-<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; <Device>-<Sm>
             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; <Device>-<Eeprom>-<ConfigData>
             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; <Device>-<sm>
             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; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Type>
         #   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; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<GroupType>
         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; <EtherCATInfo>-<Groups>-<Group>-<Type>            
-        if grouptypeflag is False: 
+
+        #  element2-2; <EtherCATInfo>-<Groups>-<Group>-<Type>
+        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; <EtherCATInfo>-<Descriptions>-<Groups>-<Group>-<Name(LcId is "1033")>
         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; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Name(LcId is "1033" or "1"?)>
         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; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Image16x14>
         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; <EtherCATInfo>-<Descriptions>-<Groups>-<Group>-<Image16x14>
         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
         #  <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Dc>-<OpMode>-<Name>
         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)
         #  <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<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)
         #  <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<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; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<CoE>
@@ -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<<bit        
+                        coe_details += 1<<bit
         eeprom.append("{:0>2x}".format(coe_details))
-        
+
         # word 4 : FoE Details and EoE Details
         #  FoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<FoE>
         if mb is not None and mb.getFoE() is not None:
@@ -1195,7 +1195,7 @@
             eeprom.append("01")
         else:
             eeprom.append("00")
-            
+
         # word 5 : SoE Channels(reserved) and DS402 Channels
         #  SoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<SoE>
         if mb is not None and mb.getSoE() is not None:
@@ -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()
--- 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()
-        
--- 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):
--- 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()
--- 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 @@
     </xsd:schema>
     """ % ("\n".join(["""\
           <xsd:attribute name="Enable%s" type="xsd:boolean"
-                         use="optional" default="false"/>""" % 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
--- 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 @@
     </xsd:schema>
 """
 
-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
-
--- 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,
--- 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)
-
--- 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
-