modbus/modbus.py
changeset 1918 e7b6478b4ebc
parent 1913 338e2f51b685
child 1919 ccea0fa6ea91
equal deleted inserted replaced
1917:d51d14719392 1918:e7b6478b4ebc
    16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    17 # GNU General Public License for more details.
    17 # GNU General Public License for more details.
    18 #
    18 #
    19 # You should have received a copy of the GNU General Public License
    19 # You should have received a copy of the GNU General Public License
    20 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
    20 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
    21 #    
    21 #
    22 # This code is made available on the understanding that it will not be
    22 # This code is made available on the understanding that it will not be
    23 # used in safety-critical situations without a full and competent review.
    23 # used in safety-critical situations without a full and competent review.
    24 
    24 
    25 
    25 
    26 
    26 import os
    27 
    27 import sys
    28 import os, sys
       
    29 base_folder = os.path.split(os.path.dirname(os.path.realpath(__file__)))[0]
       
    30 base_folder = os.path.join(base_folder, "..")
       
    31 ModbusPath  = os.path.join(base_folder, "Modbus")
       
    32 
       
    33 from mb_utils import *
    28 from mb_utils import *
    34 
    29 
    35 import wx
    30 import wx
    36 from ConfigTreeNode import ConfigTreeNode
    31 from ConfigTreeNode import ConfigTreeNode
    37 from PLCControler import LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
    32 from PLCControler import LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
    38 
    33 
    39 
    34 base_folder = os.path.split(os.path.dirname(os.path.realpath(__file__)))[0]
    40 
    35 base_folder = os.path.join(base_folder, "..")
    41 ###################################################
    36 ModbusPath = os.path.join(base_folder, "Modbus")
    42 ###################################################
    37 
    43 #                                                 #
    38 
    44 #         C L I E N T    R E Q U E S T            # 
    39 #
    45 #                                                 #
    40 #
    46 ###################################################
    41 #
    47 ###################################################
    42 # C L I E N T    R E Q U E S T            #
       
    43 #
       
    44 #
       
    45 #
    48 
    46 
    49 
    47 
    50 class _RequestPlug:
    48 class _RequestPlug:
    51     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
    49     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
    52     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    50     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    88         </xsd:complexType>
    86         </xsd:complexType>
    89       </xsd:element>
    87       </xsd:element>
    90     </xsd:schema>
    88     </xsd:schema>
    91     """
    89     """
    92 
    90 
    93     def GetParamsAttributes(self, path = None):
    91     def GetParamsAttributes(self, path=None):
    94         infos = ConfigTreeNode.GetParamsAttributes(self, path = path)
    92         infos = ConfigTreeNode.GetParamsAttributes(self, path=path)
    95         for element in infos:
    93         for element in infos:
    96             if element["name"] == "ModbusRequest":
    94             if element["name"] == "ModbusRequest":
    97                 for child in element["children"]:
    95                 for child in element["children"]:
    98                     if child["name"] == "Function":
    96                     if child["name"] == "Function":
    99                         list = modbus_function_dict.keys()
    97                         list = modbus_function_dict.keys()
   100                         list.sort()
    98                         list.sort()
   101                         child["type"] = list
    99                         child["type"] = list
   102         return infos
   100         return infos
   103       
   101 
   104     def GetVariableLocationTree(self):
   102     def GetVariableLocationTree(self):
   105         current_location = self.GetCurrentLocation()
   103         current_location = self.GetCurrentLocation()
   106         name = self.BaseParams.getName()
   104         name = self.BaseParams.getName()
   107         address = self.GetParamsAttributes()[0]["children"][3]["value"]
   105         address = self.GetParamsAttributes()[0]["children"][3]["value"]
   108         count   = self.GetParamsAttributes()[0]["children"][2]["value"]
   106         count = self.GetParamsAttributes()[0]["children"][2]["value"]
   109         function= self.GetParamsAttributes()[0]["children"][0]["value"]
   107         function = self.GetParamsAttributes()[0]["children"][0]["value"]
   110         # 'BOOL' or 'WORD'
   108         # 'BOOL' or 'WORD'
   111         datatype= modbus_function_dict[function][3]
   109         datatype = modbus_function_dict[function][3]
   112         # 1 or 16
   110         # 1 or 16
   113         datasize= modbus_function_dict[function][4]
   111         datasize = modbus_function_dict[function][4]
   114         # 'Q' for coils and holding registers, 'I' for input discretes and input registers
   112         # 'Q' for coils and holding registers, 'I' for input discretes and input registers
   115         datazone= modbus_function_dict[function][5] 
   113         datazone = modbus_function_dict[function][5]
   116         # 'X' for bits, 'W' for words
   114         # 'X' for bits, 'W' for words
   117         datatacc= modbus_function_dict[function][6] 
   115         datatacc = modbus_function_dict[function][6]
   118         # 'Coil', 'Holding Register', 'Input Discrete' or 'Input Register'
   116         # 'Coil', 'Holding Register', 'Input Discrete' or 'Input Register'
   119         dataname= modbus_function_dict[function][7] 
   117         dataname = modbus_function_dict[function][7]
   120         entries = []
   118         entries = []
   121         for offset in range(address, address+count):
   119         for offset in range(address, address + count):
   122             entries.append({
   120             entries.append({
   123                 "name": dataname + " " + str(offset),
   121                 "name": dataname + " " + str(offset),
   124                 "type": LOCATION_VAR_MEMORY,
   122                 "type": LOCATION_VAR_MEMORY,
   125                 "size": datasize,
   123                 "size": datasize,
   126                 "IEC_type": datatype,
   124                 "IEC_type": datatype,
   127                 "var_name": "var_name",
   125                 "var_name": "var_name",
   128                 "location": datatacc + ".".join([str(i) for i in current_location]) + "." + str(offset),
   126                 "location": datatacc + ".".join([str(i) for i in current_location]) + "." + str(offset),
   129                 "description": "description",
   127                 "description": "description",
   130                 "children": []})
   128                 "children": []})
   131         return  {"name": name,
   129         return {"name": name,
   132                  "type": LOCATION_CONFNODE,
   130                 "type": LOCATION_CONFNODE,
   133                  "location": ".".join([str(i) for i in current_location]) + ".x",
   131                 "location": ".".join([str(i) for i in current_location]) + ".x",
   134                  "children": entries}
   132                 "children": entries}
   135 
       
   136 
       
   137 
       
   138 
       
   139 
   133 
   140     def CTNGenerate_C(self, buildpath, locations):
   134     def CTNGenerate_C(self, buildpath, locations):
   141         """
   135         """
   142         Generate C code
   136         Generate C code
   143         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   137         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   149             "LOC" : tuple of interger for IEC location (0,1,2,...)
   143             "LOC" : tuple of interger for IEC location (0,1,2,...)
   150             }, ...]
   144             }, ...]
   151         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   145         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   152         """
   146         """
   153         return [], "", False
   147         return [], "", False
   154         
   148 
   155         
   149 
   156 ###################################################
   150 #
   157 ###################################################
   151 #
   158 #                                                 #
   152 #
   159 #     S E R V E R    M E M O R Y    A R E A       # 
   153 # S E R V E R    M E M O R Y    A R E A       #
   160 #                                                 #
   154 #
   161 ###################################################
   155 #
   162 ###################################################
   156 #
   163 
   157 
   164 #dictionary implementing:
   158 # dictionary implementing:
   165 #key - string with the description we want in the request plugin GUI
   159 # key - string with the description we want in the request plugin GUI
   166 #list - (modbus function number, request type, max count value)
   160 # list - (modbus function number, request type, max count value)
   167 modbus_memtype_dict = {"01 - Coils" :            ( '1', 'rw_bits',  65536, "BOOL", 1  , "Q", "X", "Coil"),
   161 modbus_memtype_dict = {
   168                        "02 - Input Discretes" :  ( '2', 'ro_bits',  65536, "BOOL", 1  , "I", "X", "Input Discrete"),
   162     "01 - Coils":            ('1', 'rw_bits',  65536, "BOOL", 1, "Q", "X", "Coil"),
   169                        "03 - Holding Registers" :( '3', 'rw_words', 65536, "WORD", 16 , "Q", "W", "Holding Register"),
   163     "02 - Input Discretes":  ('2', 'ro_bits',  65536, "BOOL", 1, "I", "X", "Input Discrete"),
   170                        "04 - Input Registers" :  ( '4', 'ro_words', 65536, "WORD", 16 , "I", "W", "Input Register"),
   164     "03 - Holding Registers": ('3', 'rw_words', 65536, "WORD", 16, "Q", "W", "Holding Register"),
   171                        }
   165     "04 - Input Registers":  ('4', 'ro_words', 65536, "WORD", 16, "I", "W", "Input Register"),
       
   166 }
       
   167 
   172 
   168 
   173 class _MemoryAreaPlug:
   169 class _MemoryAreaPlug:
   174     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   170     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   175     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   171     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   176       <xsd:element name="MemoryArea">
   172       <xsd:element name="MemoryArea">
   195         </xsd:complexType>
   191         </xsd:complexType>
   196       </xsd:element>
   192       </xsd:element>
   197     </xsd:schema>
   193     </xsd:schema>
   198     """
   194     """
   199 
   195 
   200     def GetParamsAttributes(self, path = None):
   196     def GetParamsAttributes(self, path=None):
   201         infos = ConfigTreeNode.GetParamsAttributes(self, path = path)
   197         infos = ConfigTreeNode.GetParamsAttributes(self, path=path)
   202         for element in infos:
   198         for element in infos:
   203             if element["name"] == "MemoryArea":
   199             if element["name"] == "MemoryArea":
   204                 for child in element["children"]:
   200                 for child in element["children"]:
   205                     if child["name"] == "MemoryAreaType":
   201                     if child["name"] == "MemoryAreaType":
   206                         list = modbus_memtype_dict.keys()
   202                         list = modbus_memtype_dict.keys()
   210 
   206 
   211     def GetVariableLocationTree(self):
   207     def GetVariableLocationTree(self):
   212         current_location = self.GetCurrentLocation()
   208         current_location = self.GetCurrentLocation()
   213         name = self.BaseParams.getName()
   209         name = self.BaseParams.getName()
   214         address = self.GetParamsAttributes()[0]["children"][2]["value"]
   210         address = self.GetParamsAttributes()[0]["children"][2]["value"]
   215         count   = self.GetParamsAttributes()[0]["children"][1]["value"]
   211         count = self.GetParamsAttributes()[0]["children"][1]["value"]
   216         function= self.GetParamsAttributes()[0]["children"][0]["value"]
   212         function = self.GetParamsAttributes()[0]["children"][0]["value"]
   217         # 'BOOL' or 'WORD'
   213         # 'BOOL' or 'WORD'
   218         datatype= modbus_memtype_dict[function][3]
   214         datatype = modbus_memtype_dict[function][3]
   219         # 1 or 16
   215         # 1 or 16
   220         datasize= modbus_memtype_dict[function][4]
   216         datasize = modbus_memtype_dict[function][4]
   221         # 'Q' for coils and holding registers, 'I' for input discretes and input registers
   217         # 'Q' for coils and holding registers, 'I' for input discretes and input registers
   222         datazone= modbus_memtype_dict[function][5] 
   218         datazone = modbus_memtype_dict[function][5]
   223         # 'X' for bits, 'W' for words
   219         # 'X' for bits, 'W' for words
   224         datatacc= modbus_memtype_dict[function][6] 
   220         datatacc = modbus_memtype_dict[function][6]
   225         # 'Coil', 'Holding Register', 'Input Discrete' or 'Input Register'
   221         # 'Coil', 'Holding Register', 'Input Discrete' or 'Input Register'
   226         dataname= modbus_memtype_dict[function][7] 
   222         dataname = modbus_memtype_dict[function][7]
   227         entries = []
   223         entries = []
   228         for offset in range(address, address+count):
   224         for offset in range(address, address + count):
   229             entries.append({
   225             entries.append({
   230                 "name": dataname + " " + str(offset),
   226                 "name": dataname + " " + str(offset),
   231                 "type": LOCATION_VAR_MEMORY,
   227                 "type": LOCATION_VAR_MEMORY,
   232                 "size": datasize,
   228                 "size": datasize,
   233                 "IEC_type": datatype,
   229                 "IEC_type": datatype,
   234                 "var_name": "var_name",
   230                 "var_name": "var_name",
   235                 "location": datatacc + ".".join([str(i) for i in current_location]) + "." + str(offset),
   231                 "location": datatacc + ".".join([str(i) for i in current_location]) + "." + str(offset),
   236                 "description": "description",
   232                 "description": "description",
   237                 "children": []})
   233                 "children": []})
   238         return  {"name": name,
   234         return {"name": name,
   239                  "type": LOCATION_CONFNODE,
   235                 "type": LOCATION_CONFNODE,
   240                  "location": ".".join([str(i) for i in current_location]) + ".x",
   236                 "location": ".".join([str(i) for i in current_location]) + ".x",
   241                  "children": entries}
   237                 "children": entries}
   242 
   238 
   243     def CTNGenerate_C(self, buildpath, locations):
   239     def CTNGenerate_C(self, buildpath, locations):
   244         """
   240         """
   245         Generate C code
   241         Generate C code
   246         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   242         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   253             }, ...]
   249             }, ...]
   254         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   250         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   255         """
   251         """
   256         return [], "", False
   252         return [], "", False
   257 
   253 
   258         
   254 
   259 ###################################################
   255 #
   260 ###################################################
   256 #
   261 #                                                 #
   257 #
   262 #            T C P    C L I E N T                 # 
   258 # T C P    C L I E N T                 #
   263 #                                                 #
   259 #
   264 ###################################################
   260 #
   265 ###################################################
   261 #
   266 
   262 
   267 class _ModbusTCPclientPlug:
   263 class _ModbusTCPclientPlug:
   268     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   264     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   269     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   265     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   270       <xsd:element name="ModbusTCPclient">
   266       <xsd:element name="ModbusTCPclient">
   281           </xsd:attribute>
   277           </xsd:attribute>
   282         </xsd:complexType>
   278         </xsd:complexType>
   283       </xsd:element>
   279       </xsd:element>
   284     </xsd:schema>
   280     </xsd:schema>
   285     """
   281     """
   286     # NOTE: Max value of 2147483647 (i32_max) for Invocation_Rate_in_ms corresponds to aprox 25 days.
   282     # NOTE: Max value of 2147483647 (i32_max) for Invocation_Rate_in_ms
   287     CTNChildrenTypes = [("ModbusRequest",_RequestPlug, "Request")]
   283     # corresponds to aprox 25 days.
       
   284     CTNChildrenTypes = [("ModbusRequest", _RequestPlug, "Request")]
   288     # TODO: Replace with CTNType !!!
   285     # TODO: Replace with CTNType !!!
   289     PlugType = "ModbusTCPclient"
   286     PlugType = "ModbusTCPclient"
   290 
   287 
   291     # Return the number of (modbus library) nodes this specific TCP client will need
   288     # Return the number of (modbus library) nodes this specific TCP client will need
   292     #   return type: (tcp nodes, rtu nodes, ascii nodes)
   289     #   return type: (tcp nodes, rtu nodes, ascii nodes)
   307         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   304         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   308         """
   305         """
   309         return [], "", False
   306         return [], "", False
   310 
   307 
   311 
   308 
   312 
   309 #
   313         
   310 #
   314 ###################################################
   311 #
   315 ###################################################
   312 # T C P    S E R V E R                 #
   316 #                                                 #
   313 #
   317 #            T C P    S E R V E R                 # 
   314 #
   318 #                                                 #
   315 #
   319 ###################################################
       
   320 ###################################################
       
   321 
   316 
   322 class _ModbusTCPserverPlug:
   317 class _ModbusTCPserverPlug:
   323     # NOTE: the Port number is a 'string' and not an 'integer'!
   318     # NOTE: the Port number is a 'string' and not an 'integer'!
   324     # This is because the underlying modbus library accepts strings 
   319     # This is because the underlying modbus library accepts strings
   325     # (e.g.: well known port names!)
   320     # (e.g.: well known port names!)
   326     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   321     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   327     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   322     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   328       <xsd:element name="ModbusServerNode">
   323       <xsd:element name="ModbusServerNode">
   329         <xsd:complexType>
   324         <xsd:complexType>
   339           </xsd:attribute>
   334           </xsd:attribute>
   340         </xsd:complexType>
   335         </xsd:complexType>
   341       </xsd:element>
   336       </xsd:element>
   342     </xsd:schema>
   337     </xsd:schema>
   343     """
   338     """
   344     CTNChildrenTypes = [("MemoryArea",_MemoryAreaPlug, "Memory Area")]
   339     CTNChildrenTypes = [("MemoryArea", _MemoryAreaPlug, "Memory Area")]
   345     # TODO: Replace with CTNType !!!
   340     # TODO: Replace with CTNType !!!
   346     PlugType = "ModbusTCPserver"
   341     PlugType = "ModbusTCPserver"
   347 
   342 
   348     # Return the number of (modbus library) nodes this specific TCP server will need
   343     # Return the number of (modbus library) nodes this specific TCP server will need
   349     #   return type: (tcp nodes, rtu nodes, ascii nodes)
   344     #   return type: (tcp nodes, rtu nodes, ascii nodes)
   353     # Return a list with a single tuple conatining the (location, port number)
   348     # Return a list with a single tuple conatining the (location, port number)
   354     #     location: location of this node in the configuration tree
   349     #     location: location of this node in the configuration tree
   355     #     port number: IP port used by this Modbus/IP server
   350     #     port number: IP port used by this Modbus/IP server
   356     def GetIPServerPortNumbers(self):
   351     def GetIPServerPortNumbers(self):
   357         port = self.GetParamsAttributes()[0]["children"][1]["value"]
   352         port = self.GetParamsAttributes()[0]["children"][1]["value"]
   358         return [(self.GetCurrentLocation() , port)]
   353         return [(self.GetCurrentLocation(), port)]
   359 
   354 
   360     def CTNGenerate_C(self, buildpath, locations):
   355     def CTNGenerate_C(self, buildpath, locations):
   361         """
   356         """
   362         Generate C code
   357         Generate C code
   363         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   358         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   371         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   366         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   372         """
   367         """
   373         return [], "", False
   368         return [], "", False
   374 
   369 
   375 
   370 
   376 
   371 #
   377 
   372 #
   378 ###################################################
   373 #
   379 ###################################################
   374 # R T U    C L I E N T                 #
   380 #                                                 #
   375 #
   381 #            R T U    C L I E N T                 # 
   376 #
   382 #                                                 #
   377 #
   383 ###################################################
       
   384 ###################################################
       
   385 
   378 
   386 class _ModbusRTUclientPlug:
   379 class _ModbusRTUclientPlug:
   387     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   380     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   388     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   381     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   389       <xsd:element name="ModbusRTUclient">
   382       <xsd:element name="ModbusRTUclient">
   402           </xsd:attribute>
   395           </xsd:attribute>
   403         </xsd:complexType>
   396         </xsd:complexType>
   404       </xsd:element>
   397       </xsd:element>
   405     </xsd:schema>
   398     </xsd:schema>
   406     """
   399     """
   407     # NOTE: Max value of 2147483647 (i32_max) for Invocation_Rate_in_ms corresponds to aprox 25 days.
   400     # NOTE: Max value of 2147483647 (i32_max) for Invocation_Rate_in_ms
   408     CTNChildrenTypes = [("ModbusRequest",_RequestPlug, "Request")]
   401     # corresponds to aprox 25 days.
       
   402     CTNChildrenTypes = [("ModbusRequest", _RequestPlug, "Request")]
   409     # TODO: Replace with CTNType !!!
   403     # TODO: Replace with CTNType !!!
   410     PlugType = "ModbusRTUclient"
   404     PlugType = "ModbusRTUclient"
   411 
   405 
   412     def GetParamsAttributes(self, path = None):
   406     def GetParamsAttributes(self, path=None):
   413         infos = ConfigTreeNode.GetParamsAttributes(self, path = path)
   407         infos = ConfigTreeNode.GetParamsAttributes(self, path=path)
   414         for element in infos:
   408         for element in infos:
   415             if element["name"] == "ModbusRTUclient":
   409             if element["name"] == "ModbusRTUclient":
   416                 for child in element["children"]:
   410                 for child in element["children"]:
   417                     if child["name"] == "Baud_Rate":
   411                     if child["name"] == "Baud_Rate":
   418                         child["type"] = modbus_serial_baudrate_list
   412                         child["type"] = modbus_serial_baudrate_list
   419                     if child["name"] == "Stop_Bits":
   413                     if child["name"] == "Stop_Bits":
   420                         child["type"] = modbus_serial_stopbits_list
   414                         child["type"] = modbus_serial_stopbits_list
   421                     if child["name"] == "Parity":
   415                     if child["name"] == "Parity":
   422                         child["type"] = modbus_serial_parity_dict.keys()
   416                         child["type"] = modbus_serial_parity_dict.keys()
   423         return infos
   417         return infos
   424       
   418 
   425     # Return the number of (modbus library) nodes this specific RTU client will need
   419     # Return the number of (modbus library) nodes this specific RTU client will need
   426     #   return type: (tcp nodes, rtu nodes, ascii nodes)
   420     #   return type: (tcp nodes, rtu nodes, ascii nodes)
   427     def GetNodeCount(self):
   421     def GetNodeCount(self):
   428         return (0, 1, 0)
   422         return (0, 1, 0)
   429 
   423 
   441         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   435         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   442         """
   436         """
   443         return [], "", False
   437         return [], "", False
   444 
   438 
   445 
   439 
   446 
   440 #
   447 ###################################################
   441 #
   448 ###################################################
   442 #
   449 #                                                 #
   443 # R T U    S L A V E                   #
   450 #            R T U    S L A V E                   # 
   444 #
   451 #                                                 #
   445 #
   452 ###################################################
   446 #
   453 ###################################################
       
   454 
   447 
   455 
   448 
   456 class _ModbusRTUslavePlug:
   449 class _ModbusRTUslavePlug:
   457     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   450     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   458     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   451     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   472           </xsd:attribute>
   465           </xsd:attribute>
   473         </xsd:complexType>
   466         </xsd:complexType>
   474       </xsd:element>
   467       </xsd:element>
   475     </xsd:schema>
   468     </xsd:schema>
   476     """
   469     """
   477     CTNChildrenTypes = [("MemoryArea",_MemoryAreaPlug, "Memory Area")]
   470     CTNChildrenTypes = [("MemoryArea", _MemoryAreaPlug, "Memory Area")]
   478     # TODO: Replace with CTNType !!!
   471     # TODO: Replace with CTNType !!!
   479     PlugType = "ModbusRTUslave"
   472     PlugType = "ModbusRTUslave"
   480 
   473 
   481     def GetParamsAttributes(self, path = None):
   474     def GetParamsAttributes(self, path=None):
   482         infos = ConfigTreeNode.GetParamsAttributes(self, path = path)
   475         infos = ConfigTreeNode.GetParamsAttributes(self, path=path)
   483         for element in infos:
   476         for element in infos:
   484             if element["name"] == "ModbusRTUslave":
   477             if element["name"] == "ModbusRTUslave":
   485                 for child in element["children"]:
   478                 for child in element["children"]:
   486                     if child["name"] == "Baud_Rate":
   479                     if child["name"] == "Baud_Rate":
   487                         child["type"] = modbus_serial_baudrate_list
   480                         child["type"] = modbus_serial_baudrate_list
   488                     if child["name"] == "Stop_Bits":
   481                     if child["name"] == "Stop_Bits":
   489                         child["type"] = modbus_serial_stopbits_list
   482                         child["type"] = modbus_serial_stopbits_list
   490                     if child["name"] == "Parity":
   483                     if child["name"] == "Parity":
   491                         child["type"] = modbus_serial_parity_dict.keys()
   484                         child["type"] = modbus_serial_parity_dict.keys()
   492         return infos
   485         return infos
   493       
   486 
   494     # Return the number of (modbus library) nodes this specific RTU slave will need
   487     # Return the number of (modbus library) nodes this specific RTU slave will need
   495     #   return type: (tcp nodes, rtu nodes, ascii nodes)
   488     #   return type: (tcp nodes, rtu nodes, ascii nodes)
   496     def GetNodeCount(self):
   489     def GetNodeCount(self):
   497         return (0, 1, 0)
   490         return (0, 1, 0)
   498 
   491 
   509             }, ...]
   502             }, ...]
   510         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   503         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   511         """
   504         """
   512         return [], "", False
   505         return [], "", False
   513 
   506 
   514     
   507 
   515 
   508 def _lt_to_str(loctuple):
   516 ###################################################
   509     return '.'.join(map(str, loctuple))
   517 ###################################################
   510 
   518 #                                                 #
   511 
   519 #             R O O T    C L A S S                # 
   512 #
   520 #                                                 #
   513 #
   521 ###################################################
   514 #
   522 ###################################################
   515 # R O O T    C L A S S                #
       
   516 #
       
   517 #
       
   518 #
   523 class RootClass:
   519 class RootClass:
   524     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   520     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   525     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   521     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   526       <xsd:element name="ModbusRoot">
   522       <xsd:element name="ModbusRoot">
   527         <xsd:complexType>
   523         <xsd:complexType>
   535           </xsd:attribute>
   531           </xsd:attribute>
   536         </xsd:complexType>
   532         </xsd:complexType>
   537       </xsd:element>
   533       </xsd:element>
   538     </xsd:schema>
   534     </xsd:schema>
   539     """
   535     """
   540     CTNChildrenTypes = [("ModbusTCPclient",_ModbusTCPclientPlug, "Modbus TCP Client")
   536     CTNChildrenTypes = [("ModbusTCPclient", _ModbusTCPclientPlug, "Modbus TCP Client"), ("ModbusTCPserver", _ModbusTCPserverPlug, "Modbus TCP Server"), ("ModbusRTUclient", _ModbusRTUclientPlug, "Modbus RTU Client"), ("ModbusRTUslave", _ModbusRTUslavePlug,  "Modbus RTU Slave")
   541                        ,("ModbusTCPserver",_ModbusTCPserverPlug, "Modbus TCP Server")
   537                         ]
   542                        ,("ModbusRTUclient",_ModbusRTUclientPlug, "Modbus RTU Client")
   538 
   543                        ,("ModbusRTUslave", _ModbusRTUslavePlug,  "Modbus RTU Slave")
       
   544                        ]
       
   545     
       
   546     # Return the number of (modbus library) nodes this specific instance of the modbus plugin will need
   539     # Return the number of (modbus library) nodes this specific instance of the modbus plugin will need
   547     #   return type: (tcp nodes, rtu nodes, ascii nodes)
   540     #   return type: (tcp nodes, rtu nodes, ascii nodes)
   548     def GetNodeCount(self):
   541     def GetNodeCount(self):
   549         max_remote_tcpclient = self.GetParamsAttributes()[0]["children"][0]["value"]
   542         max_remote_tcpclient = self.GetParamsAttributes()[
       
   543             0]["children"][0]["value"]
   550         total_node_count = (max_remote_tcpclient, 0, 0)
   544         total_node_count = (max_remote_tcpclient, 0, 0)
   551         for child in self.IECSortedChildren():
   545         for child in self.IECSortedChildren():
   552             # ask each child how many nodes it needs, and add them all up.
   546             # ask each child how many nodes it needs, and add them all up.
   553             total_node_count = tuple(x1 + x2 for x1, x2 in zip(total_node_count, child.GetNodeCount())) 
   547             total_node_count = tuple(
       
   548                 x1 + x2 for x1, x2 in zip(total_node_count, child.GetNodeCount()))
   554         return total_node_count
   549         return total_node_count
   555 
   550 
   556     # Return a list with tuples of the (location, port numbers) used by all the Modbus/IP servers
   551     # Return a list with tuples of the (location, port numbers) used by all
       
   552     # the Modbus/IP servers
   557     def GetIPServerPortNumbers(self):
   553     def GetIPServerPortNumbers(self):
   558         IPServer_port_numbers = []
   554         IPServer_port_numbers = []
   559         for child in self.IECSortedChildren():
   555         for child in self.IECSortedChildren():
   560             if child.CTNType == "ModbusTCPserver":
   556             if child.CTNType == "ModbusTCPserver":
   561                 IPServer_port_numbers.extend(child.GetIPServerPortNumbers())
   557                 IPServer_port_numbers.extend(child.GetIPServerPortNumbers())
   562         return IPServer_port_numbers
   558         return IPServer_port_numbers
   563 
   559 
   564     def CTNGenerate_C(self, buildpath, locations):
   560     def CTNGenerate_C(self, buildpath, locations):
   565         #print "#############"
   561         # print "#############"
   566         #print self.__class__
   562         # print self.__class__
   567         #print type(self)
   563         # print type(self)
   568         #print "self.CTNType >>>"
   564         # print "self.CTNType >>>"
   569         #print self.CTNType
   565         # print self.CTNType
   570         #print "type(self.CTNType) >>>"
   566         # print "type(self.CTNType) >>>"
   571         #print type(self.CTNType)
   567         # print type(self.CTNType)
   572         #print "#############"
   568         # print "#############"
   573         
   569 
   574         loc_dict = {"locstr" : "_".join(map(str,self.GetCurrentLocation())),
   570         loc_dict = {"locstr": "_".join(map(str, self.GetCurrentLocation())),
   575                    }
   571                     }
   576         
   572 
   577         # Determine the number of (modbus library) nodes ALL instances of the modbus plugin will need
   573         # Determine the number of (modbus library) nodes ALL instances of the modbus plugin will need
   578         #   total_node_count: (tcp nodes, rtu nodes, ascii nodes)
   574         #   total_node_count: (tcp nodes, rtu nodes, ascii nodes)
   579         # Also get a list with tuples of (location, IP port numbers) used by all the Modbus/IP server nodes
   575         # Also get a list with tuples of (location, IP port numbers) used by all the Modbus/IP server nodes
   580         #   This list is later used to search for duplicates in port numbers!
   576         #   This list is later used to search for duplicates in port numbers!
   581         #   IPServer_port_numbers = [(location ,IPserver_port_number), ...]
   577         #   IPServer_port_numbers = [(location ,IPserver_port_number), ...]
   582         #       location: tuple similar to (0, 3, 1) representing the location in the configuration tree "0.3.1.x"
   578         #       location: tuple similar to (0, 3, 1) representing the location in the configuration tree "0.3.1.x"
   583         #       IPserver_port_number: a number (i.e. port number used by the Modbus/IP server)
   579         # IPserver_port_number: a number (i.e. port number used by the
       
   580         # Modbus/IP server)
   584         total_node_count = (0, 0, 0)
   581         total_node_count = (0, 0, 0)
   585         IPServer_port_numbers = []
   582         IPServer_port_numbers = []
   586         for CTNInstance in self.GetCTRoot().IterChildren():
   583         for CTNInstance in self.GetCTRoot().IterChildren():
   587             if CTNInstance.CTNType == "modbus":
   584             if CTNInstance.CTNType == "modbus":
   588                 # ask each modbus plugin instance how many nodes it needs, and add them all up.
   585                 # ask each modbus plugin instance how many nodes it needs, and
   589                 total_node_count = tuple(x1 + x2 for x1, x2 in zip(total_node_count, CTNInstance.GetNodeCount())) 
   586                 # add them all up.
   590                 IPServer_port_numbers.extend(CTNInstance.GetIPServerPortNumbers())
   587                 total_node_count = tuple(x1 + x2 for x1, x2 in zip(
       
   588                     total_node_count, CTNInstance.GetNodeCount()))
       
   589                 IPServer_port_numbers.extend(
       
   590                     CTNInstance.GetIPServerPortNumbers())
   591 
   591 
   592         # Search for use of duplicate port numbers by Modbus/IP servers
   592         # Search for use of duplicate port numbers by Modbus/IP servers
   593         #print IPServer_port_numbers 
   593         # print IPServer_port_numbers
   594         # ..but first define a lambda function to convert a tuple with the config tree location to a nice looking string
   594         # ..but first define a lambda function to convert a tuple with the config tree location to a nice looking string
   595         #   for e.g., convert the tuple (0, 3, 4) to "0.3.4" 
   595         #   for e.g., convert the tuple (0, 3, 4) to "0.3.4"
   596         lt_to_str = lambda loctuple: '.'.join(map(str, loctuple))
   596 
   597         for i in range(0, len(IPServer_port_numbers)-1):
   597         for i in range(0, len(IPServer_port_numbers) - 1):
   598             for j in range (i+1, len(IPServer_port_numbers)):
   598             for j in range(i + 1, len(IPServer_port_numbers)):
   599                 if IPServer_port_numbers[i][1] == IPServer_port_numbers[j][1]:
   599                 if IPServer_port_numbers[i][1] == IPServer_port_numbers[j][1]:
   600                     self.GetCTRoot().logger.write_warning(_("Error: Modbus/IP Servers %s.x and %s.x use the same port number %s.\n")%(lt_to_str(IPServer_port_numbers[i][0]), lt_to_str(IPServer_port_numbers[j][0]), IPServer_port_numbers[j][1]))
   600                     self.GetCTRoot().logger.write_warning(
   601                     raise Exception, False
   601                         _("Error: Modbus/IP Servers %s.x and %s.x use the same port number %s.\n") % (
   602                     # TODO: return an error code instead of raising an exception
   602                             _lt_to_str(IPServer_port_numbers[i][0]),
   603         
   603                             _lt_to_str(IPServer_port_numbers[j][0]),
   604         # Determine the current location in Beremiz's project configuration tree 
   604                             IPServer_port_numbers[j][1]))
       
   605                     raise Exception
       
   606                     # TODO: return an error code instead of raising an
       
   607                     # exception
       
   608 
       
   609         # Determine the current location in Beremiz's project configuration
       
   610         # tree
   605         current_location = self.GetCurrentLocation()
   611         current_location = self.GetCurrentLocation()
   606         
   612 
   607         # define a unique name for the generated C and h files
   613         # define a unique name for the generated C and h files
   608         prefix = "_".join(map(str, current_location))
   614         prefix = "_".join(map(str, current_location))
   609         Gen_MB_c_path = os.path.join(buildpath, "MB_%s.c"%prefix)
   615         Gen_MB_c_path = os.path.join(buildpath, "MB_%s.c" % prefix)
   610         Gen_MB_h_path = os.path.join(buildpath, "MB_%s.h"%prefix) 
   616         Gen_MB_h_path = os.path.join(buildpath, "MB_%s.h" % prefix)
   611         c_filename = os.path.join(os.path.split(__file__)[0],"mb_runtime.c")
   617         c_filename = os.path.join(os.path.split(__file__)[0], "mb_runtime.c")
   612         h_filename = os.path.join(os.path.split(__file__)[0],"mb_runtime.h")
   618         h_filename = os.path.join(os.path.split(__file__)[0], "mb_runtime.h")
   613 
   619 
   614         tcpclient_reqs_count = 0
   620         tcpclient_reqs_count = 0
   615         rtuclient_reqs_count = 0
   621         rtuclient_reqs_count = 0
   616         ascclient_reqs_count = 0
   622         ascclient_reqs_count = 0
   617         tcpclient_node_count = 0
   623         tcpclient_node_count = 0
   622         ascserver_node_count = 0
   628         ascserver_node_count = 0
   623         nodeid = 0
   629         nodeid = 0
   624         client_nodeid = 0
   630         client_nodeid = 0
   625         client_requestid = 0
   631         client_requestid = 0
   626         server_id = 0
   632         server_id = 0
   627         
   633 
   628         server_node_list = []
   634         server_node_list = []
   629         client_node_list = []
   635         client_node_list = []
   630         client_request_list = []
   636         client_request_list = []
   631         server_memarea_list = []
   637         server_memarea_list = []
   632         loc_vars = []
   638         loc_vars = []
   633         loc_vars_list = [] # list of variables already declared in C code!
   639         loc_vars_list = []  # list of variables already declared in C code!
   634         for child in self.IECSortedChildren():
   640         for child in self.IECSortedChildren():
   635             #print "<<<<<<<<<<<<<"
   641             # print "<<<<<<<<<<<<<"
   636             #print "child (self.IECSortedChildren())----->"
   642             # print "child (self.IECSortedChildren())----->"
   637             #print child.__class__
   643             # print child.__class__
   638             #print ">>>>>>>>>>>>>"
   644             # print ">>>>>>>>>>>>>"
   639             ######################################
   645             #
   640             if child.PlugType == "ModbusTCPserver":
   646             if child.PlugType == "ModbusTCPserver":
   641                 tcpserver_node_count += 1
   647                 tcpserver_node_count += 1
   642                 new_node = GetTCPServerNodePrinted(self, child)
   648                 new_node = GetTCPServerNodePrinted(self, child)
   643                 if new_node is None:
   649                 if new_node is None:
   644                     return [],"",False
   650                     return [], "", False
   645                 server_node_list.append(new_node)
   651                 server_node_list.append(new_node)
   646                 ##############
   652                 #
   647                 for subchild in child.IECSortedChildren():
   653                 for subchild in child.IECSortedChildren():
   648                     new_memarea = GetTCPServerMemAreaPrinted(self, subchild, nodeid)
   654                     new_memarea = GetTCPServerMemAreaPrinted(
       
   655                         self, subchild, nodeid)
   649                     if new_memarea is None:
   656                     if new_memarea is None:
   650                         return [],"",False
   657                         return [], "", False
   651                     server_memarea_list.append(new_memarea)
   658                     server_memarea_list.append(new_memarea)
   652                     function= subchild.GetParamsAttributes()[0]["children"][0]["value"]
   659                     function = subchild.GetParamsAttributes()[
       
   660                         0]["children"][0]["value"]
   653                     # 'ro_bits', 'rw_bits', 'ro_words' or 'rw_words'
   661                     # 'ro_bits', 'rw_bits', 'ro_words' or 'rw_words'
   654                     memarea= modbus_memtype_dict[function][1]
   662                     memarea = modbus_memtype_dict[function][1]
   655                     for iecvar in subchild.GetLocations():
   663                     for iecvar in subchild.GetLocations():
   656                         #print repr(iecvar)
   664                         # print repr(iecvar)
   657                         absloute_address = iecvar["LOC"][3]
   665                         absloute_address = iecvar["LOC"][3]
   658                         start_address = int(subchild.GetParamsAttributes()[0]["children"][2]["value"])
   666                         start_address = int(GetCTVal(child, 2))
   659                         relative_addr = absloute_address - start_address
   667                         relative_addr = absloute_address - start_address
   660                         #test if relative address in request specified range
   668                         # test if relative address in request specified range
   661                         if relative_addr in xrange(int(subchild.GetParamsAttributes()[0]["children"][1]["value"])):
   669                         if relative_addr in xrange(int(GetCTVal(child, 1))):
   662                             if str(iecvar["NAME"]) not in loc_vars_list:
   670                             if str(iecvar["NAME"]) not in loc_vars_list:
   663                                 loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.%s[%d];" % (server_id, memarea, absloute_address))
   671                                 loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.%s[%d];" % (
       
   672                                     server_id, memarea, absloute_address))
   664                                 loc_vars_list.append(str(iecvar["NAME"]))
   673                                 loc_vars_list.append(str(iecvar["NAME"]))
   665                 server_id += 1
   674                 server_id += 1
   666             ######################################
   675             #
   667             if child.PlugType == "ModbusRTUslave":
   676             if child.PlugType == "ModbusRTUslave":
   668                 rtuserver_node_count += 1
   677                 rtuserver_node_count += 1
   669                 new_node = GetRTUSlaveNodePrinted(self, child)
   678                 new_node = GetRTUSlaveNodePrinted(self, child)
   670                 if new_node is None:
   679                 if new_node is None:
   671                     return [],"",False
   680                     return [], "", False
   672                 server_node_list.append(new_node)
   681                 server_node_list.append(new_node)
   673                 ##############
   682                 #
   674                 for subchild in child.IECSortedChildren():
   683                 for subchild in child.IECSortedChildren():
   675                     new_memarea = GetTCPServerMemAreaPrinted(self, subchild, nodeid)
   684                     new_memarea = GetTCPServerMemAreaPrinted(
       
   685                         self, subchild, nodeid)
   676                     if new_memarea is None:
   686                     if new_memarea is None:
   677                         return [],"",False
   687                         return [], "", False
   678                     server_memarea_list.append(new_memarea)
   688                     server_memarea_list.append(new_memarea)
   679                     function= subchild.GetParamsAttributes()[0]["children"][0]["value"]
   689                     function = subchild.GetParamsAttributes()[
       
   690                         0]["children"][0]["value"]
   680                     # 'ro_bits', 'rw_bits', 'ro_words' or 'rw_words'
   691                     # 'ro_bits', 'rw_bits', 'ro_words' or 'rw_words'
   681                     memarea= modbus_memtype_dict[function][1]
   692                     memarea = modbus_memtype_dict[function][1]
   682                     for iecvar in subchild.GetLocations():
   693                     for iecvar in subchild.GetLocations():
   683                         #print repr(iecvar)
   694                         # print repr(iecvar)
   684                         absloute_address = iecvar["LOC"][3]
   695                         absloute_address = iecvar["LOC"][3]
   685                         start_address = int(subchild.GetParamsAttributes()[0]["children"][2]["value"])
   696                         start_address = int(GetCTVal(child, 2))
   686                         relative_addr = absloute_address - start_address
   697                         relative_addr = absloute_address - start_address
   687                         #test if relative address in request specified range
   698                         # test if relative address in request specified range
   688                         if relative_addr in xrange(int(subchild.GetParamsAttributes()[0]["children"][1]["value"])):
   699                         if relative_addr in xrange(int(GetCTVal(child, 1))):
   689                             if str(iecvar["NAME"]) not in loc_vars_list:
   700                             if str(iecvar["NAME"]) not in loc_vars_list:
   690                                 loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.%s[%d];" % (server_id, memarea, absloute_address))
   701                                 loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.%s[%d];" % (
       
   702                                     server_id, memarea, absloute_address))
   691                                 loc_vars_list.append(str(iecvar["NAME"]))
   703                                 loc_vars_list.append(str(iecvar["NAME"]))
   692                 server_id += 1
   704                 server_id += 1
   693             ######################################
   705             #
   694             if child.PlugType == "ModbusTCPclient":
   706             if child.PlugType == "ModbusTCPclient":
   695                 tcpclient_reqs_count += len(child.IECSortedChildren())
   707                 tcpclient_reqs_count += len(child.IECSortedChildren())
   696                 new_node = GetTCPClientNodePrinted(self, child)
   708                 new_node = GetTCPClientNodePrinted(self, child)
   697                 if new_node is None:
   709                 if new_node is None:
   698                     return [],"",False
   710                     return [], "", False
   699                 client_node_list.append(new_node)
   711                 client_node_list.append(new_node)
   700                 for subchild in child.IECSortedChildren():
   712                 for subchild in child.IECSortedChildren():
   701                     new_req = GetClientRequestPrinted(self, subchild, client_nodeid)
   713                     new_req = GetClientRequestPrinted(
       
   714                         self, subchild, client_nodeid)
   702                     if new_req is None:
   715                     if new_req is None:
   703                         return [],"",False
   716                         return [], "", False
   704                     client_request_list.append(new_req)
   717                     client_request_list.append(new_req)
   705                     for iecvar in subchild.GetLocations():
   718                     for iecvar in subchild.GetLocations():
   706                         #absloute address - start address
   719                         # absloute address - start address
   707                         relative_addr = iecvar["LOC"][3] - int(subchild.GetParamsAttributes()[0]["children"][3]["value"])
   720                         relative_addr = iecvar["LOC"][3] - int(GetCTVal(child, 3))
   708                         #test if relative address in request specified range
   721                         # test if relative address in request specified range
   709                         if relative_addr in xrange(int(subchild.GetParamsAttributes()[0]["children"][2]["value"])):
   722                         if relative_addr in xrange(int(GetCTVal(child, 2))):
   710                             if str(iecvar["NAME"]) not in loc_vars_list:
   723                             if str(iecvar["NAME"]) not in loc_vars_list:
   711                                 loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &client_requests[%d].plcv_buffer[%d];" % (client_requestid, relative_addr))
   724                                 loc_vars.append(
       
   725                                     "u16 *" + str(iecvar["NAME"]) + " = &client_requests[%d].plcv_buffer[%d];" % (client_requestid, relative_addr))
   712                                 loc_vars_list.append(str(iecvar["NAME"]))
   726                                 loc_vars_list.append(str(iecvar["NAME"]))
   713                     client_requestid += 1
   727                     client_requestid += 1
   714                 tcpclient_node_count += 1
   728                 tcpclient_node_count += 1
   715                 client_nodeid += 1
   729                 client_nodeid += 1
   716             ######################################
   730             #
   717             if child.PlugType == "ModbusRTUclient":
   731             if child.PlugType == "ModbusRTUclient":
   718                 rtuclient_reqs_count += len(child.IECSortedChildren())
   732                 rtuclient_reqs_count += len(child.IECSortedChildren())
   719                 new_node = GetRTUClientNodePrinted(self, child)
   733                 new_node = GetRTUClientNodePrinted(self, child)
   720                 if new_node is None:
   734                 if new_node is None:
   721                     return [],"",False
   735                     return [], "", False
   722                 client_node_list.append(new_node)
   736                 client_node_list.append(new_node)
   723                 for subchild in child.IECSortedChildren():
   737                 for subchild in child.IECSortedChildren():
   724                     new_req = GetClientRequestPrinted(self, subchild, client_nodeid)
   738                     new_req = GetClientRequestPrinted(
       
   739                         self, subchild, client_nodeid)
   725                     if new_req is None:
   740                     if new_req is None:
   726                         return [],"",False
   741                         return [], "", False
   727                     client_request_list.append(new_req)
   742                     client_request_list.append(new_req)
   728                     for iecvar in subchild.GetLocations():
   743                     for iecvar in subchild.GetLocations():
   729                         #absloute address - start address
   744                         # absloute address - start address
   730                         relative_addr = iecvar["LOC"][3] - int(subchild.GetParamsAttributes()[0]["children"][3]["value"])
   745                         relative_addr = iecvar["LOC"][3] - int(GetCTVal(child, 3))
   731                         #test if relative address in request specified range
   746                         # test if relative address in request specified range
   732                         if relative_addr in xrange(int(subchild.GetParamsAttributes()[0]["children"][2]["value"])):
   747                         if relative_addr in xrange(int(GetCTVal(child, 2))):
   733                             if str(iecvar["NAME"]) not in loc_vars_list:
   748                             if str(iecvar["NAME"]) not in loc_vars_list:
   734                                 loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &client_requests[%d].plcv_buffer[%d];" % (client_requestid, relative_addr))
   749                                 loc_vars.append(
       
   750                                     "u16 *" + str(iecvar["NAME"]) + " = &client_requests[%d].plcv_buffer[%d];" % (client_requestid, relative_addr))
   735                                 loc_vars_list.append(str(iecvar["NAME"]))
   751                                 loc_vars_list.append(str(iecvar["NAME"]))
   736                     client_requestid += 1
   752                     client_requestid += 1
   737                 rtuclient_node_count += 1
   753                 rtuclient_node_count += 1
   738                 client_nodeid += 1
   754                 client_nodeid += 1
   739             nodeid += 1
   755             nodeid += 1
   740         
   756 
   741         loc_dict["loc_vars"]             = "\n".join(loc_vars)
   757         loc_dict["loc_vars"] = "\n".join(loc_vars)
   742         loc_dict["server_nodes_params"]  = ",\n\n".join(server_node_list)
   758         loc_dict["server_nodes_params"] = ",\n\n".join(server_node_list)
   743         loc_dict["client_nodes_params"]  = ",\n\n".join(client_node_list)
   759         loc_dict["client_nodes_params"] = ",\n\n".join(client_node_list)
   744         loc_dict["client_req_params"]    = ",\n\n".join(client_request_list)
   760         loc_dict["client_req_params"] = ",\n\n".join(client_request_list)
   745         loc_dict["tcpclient_reqs_count"] = str(tcpclient_reqs_count)
   761         loc_dict["tcpclient_reqs_count"] = str(tcpclient_reqs_count)
   746         loc_dict["tcpclient_node_count"] = str(tcpclient_node_count)
   762         loc_dict["tcpclient_node_count"] = str(tcpclient_node_count)
   747         loc_dict["tcpserver_node_count"] = str(tcpserver_node_count)
   763         loc_dict["tcpserver_node_count"] = str(tcpserver_node_count)
   748         loc_dict["rtuclient_reqs_count"] = str(rtuclient_reqs_count)
   764         loc_dict["rtuclient_reqs_count"] = str(rtuclient_reqs_count)
   749         loc_dict["rtuclient_node_count"] = str(rtuclient_node_count)
   765         loc_dict["rtuclient_node_count"] = str(rtuclient_node_count)
   750         loc_dict["rtuserver_node_count"] = str(rtuserver_node_count)
   766         loc_dict["rtuserver_node_count"] = str(rtuserver_node_count)
   751         loc_dict["ascclient_reqs_count"] = str(ascclient_reqs_count)
   767         loc_dict["ascclient_reqs_count"] = str(ascclient_reqs_count)
   752         loc_dict["ascclient_node_count"] = str(ascclient_node_count)
   768         loc_dict["ascclient_node_count"] = str(ascclient_node_count)
   753         loc_dict["ascserver_node_count"] = str(ascserver_node_count)
   769         loc_dict["ascserver_node_count"] = str(ascserver_node_count)
   754         loc_dict["total_tcpnode_count"]  = str(total_node_count[0])
   770         loc_dict["total_tcpnode_count"] = str(total_node_count[0])
   755         loc_dict["total_rtunode_count"]  = str(total_node_count[1])
   771         loc_dict["total_rtunode_count"] = str(total_node_count[1])
   756         loc_dict["total_ascnode_count"]  = str(total_node_count[2])
   772         loc_dict["total_ascnode_count"] = str(total_node_count[2])
   757         loc_dict["max_remote_tcpclient"] = int(self.GetParamsAttributes()[0]["children"][0]["value"])
   773         loc_dict["max_remote_tcpclient"] = int(
   758 
   774             self.GetParamsAttributes()[0]["children"][0]["value"])
   759         #get template file content into a string, format it with dict
   775 
   760         #and write it to proper .h file
   776         # get template file content into a string, format it with dict
       
   777         # and write it to proper .h file
   761         mb_main = open(h_filename).read() % loc_dict
   778         mb_main = open(h_filename).read() % loc_dict
   762         f = open(Gen_MB_h_path,'w')
   779         f = open(Gen_MB_h_path, 'w')
   763         f.write(mb_main)
   780         f.write(mb_main)
   764         f.close()
   781         f.close()
   765         #same thing as above, but now to .c file
   782         # same thing as above, but now to .c file
   766         mb_main = open(c_filename).read() % loc_dict
   783         mb_main = open(c_filename).read() % loc_dict
   767         f = open(Gen_MB_c_path,'w')
   784         f = open(Gen_MB_c_path, 'w')
   768         f.write(mb_main)
   785         f.write(mb_main)
   769         f.close()
   786         f.close()
   770 
   787 
   771         LDFLAGS = []
   788         LDFLAGS = []
   772         LDFLAGS.append(" \"-L" + ModbusPath + "\"")
   789         LDFLAGS.append(" \"-L" + ModbusPath + "\"")
   773         LDFLAGS.append(" -lmb ")
   790         LDFLAGS.append(" -lmb ")
   774         LDFLAGS.append(" \"-Wl,-rpath," + ModbusPath + "\"")
   791         LDFLAGS.append(" \"-Wl,-rpath," + ModbusPath + "\"")
   775         #LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_slave_and_master.o") + "\"")
   792         # LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_slave_and_master.o") + "\"")
   776         #LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_slave.o") + "\"")
   793         # LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_slave.o") + "\"")
   777         #LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_master.o") + "\"")
   794         # LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_master.o") + "\"")
   778         #LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_tcp.o")    + "\"")
   795         # LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_tcp.o")    + "\"")
   779         #LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_rtu.o")    + "\"")
   796         # LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_rtu.o")    + "\"")
   780         #LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_ascii.o")    + "\"")
   797         # LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_ascii.o")    + "\"")
   781         #LDFLAGS.append("\"" + os.path.join(ModbusPath, "sin_util.o")  + "\"")
   798         # LDFLAGS.append("\"" + os.path.join(ModbusPath, "sin_util.o")  + "\"")
   782         # Target is ARM with linux and not win on x86 so winsock2 (ws2_32) library is useless !!!
   799         # Target is ARM with linux and not win on x86 so winsock2 (ws2_32) library is useless !!!
   783         #if os.name == 'nt':   # other possible values: 'posix' 'os2' 'ce' 'java' 'riscos'
   800         # if os.name == 'nt':   # other possible values: 'posix' 'os2' 'ce' 'java' 'riscos'
   784         #    LDFLAGS.append(" -lws2_32 ")  # on windows we need to load winsock library!        
   801         # LDFLAGS.append(" -lws2_32 ")  # on windows we need to load winsock
   785 
   802         # library!
   786         return [(Gen_MB_c_path, ' -I"'+ModbusPath+'"')], LDFLAGS, True
   803 
       
   804         return [(Gen_MB_c_path, ' -I"' + ModbusPath + '"')], LDFLAGS, True