diff -r de4ee16f7c6c -r bb883e063175 modbus/modbus.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modbus/modbus.py Sun Mar 05 00:37:54 2017 +0000 @@ -0,0 +1,785 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# This file is part of Beremiz, a Integrated Development Environment for +# programming IEC 61131-3 automates supporting plcopen standard and CanFestival. +# +# Copyright (c) 2016 Mario de Sousa (msousa@fe.up.pt) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# This code is made available on the understanding that it will not be +# used in safety-critical situations without a full and competent review. + + + + +import os, sys +base_folder = os.path.split(os.path.dirname(os.path.realpath(__file__)))[0] +base_folder = os.path.join(base_folder, "..") +ModbusPath = os.path.join(base_folder, "Modbus") + +from mb_utils import * + +import wx +from ConfigTreeNode import ConfigTreeNode +from PLCControler import LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY + + + +################################################### +################################################### +# # +# C L I E N T R E Q U E S T # +# # +################################################### +################################################### + + +class _RequestPlug: + XSD = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + def GetParamsAttributes(self, path = None): + infos = ConfigTreeNode.GetParamsAttributes(self, path = path) + for element in infos: + if element["name"] == "ModbusRequest": + for child in element["children"]: + if child["name"] == "Function": + list = modbus_function_dict.keys() + list.sort() + child["type"] = list + return infos + + def GetVariableLocationTree(self): + current_location = self.GetCurrentLocation() + name = self.BaseParams.getName() + address = self.GetParamsAttributes()[0]["children"][3]["value"] + count = self.GetParamsAttributes()[0]["children"][2]["value"] + function= self.GetParamsAttributes()[0]["children"][0]["value"] + # 'BOOL' or 'WORD' + datatype= modbus_function_dict[function][3] + # 1 or 16 + datasize= modbus_function_dict[function][4] + # 'Q' for coils and holding registers, 'I' for input discretes and input registers + datazone= modbus_function_dict[function][5] + # 'X' for bits, 'W' for words + datatacc= modbus_function_dict[function][6] + # 'Coil', 'Holding Register', 'Input Discrete' or 'Input Register' + dataname= modbus_function_dict[function][7] + entries = [] + for offset in range(address, address+count): + entries.append({ + "name": dataname + " " + str(offset), + "type": LOCATION_VAR_MEMORY, + "size": datasize, + "IEC_type": datatype, + "var_name": "var_name", + "location": datatacc + ".".join([str(i) for i in current_location]) + "." + str(offset), + "description": "description", + "children": []}) + return {"name": name, + "type": LOCATION_CONFNODE, + "location": ".".join([str(i) for i in current_location]) + ".x", + "children": entries} + + + + + + def CTNGenerate_C(self, buildpath, locations): + """ + Generate C code + @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5) + @param locations: List of complete variables locations \ + [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...) + "NAME" : name of the variable (generally "__IW0_1_2" style) + "DIR" : direction "Q","I" or "M" + "SIZE" : size "X", "B", "W", "D", "L" + "LOC" : tuple of interger for IEC location (0,1,2,...) + }, ...] + @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND + """ + return [], "", False + + +################################################### +################################################### +# # +# S E R V E R M E M O R Y A R E A # +# # +################################################### +################################################### + +#dictionary implementing: +#key - string with the description we want in the request plugin GUI +#list - (modbus function number, request type, max count value) +modbus_memtype_dict = {"01 - Coils" : ( '1', 'rw_bits', 65536, "BOOL", 1 , "Q", "X", "Coil"), + "02 - Input Discretes" : ( '2', 'ro_bits', 65536, "BOOL", 1 , "I", "X", "Input Discrete"), + "03 - Holding Registers" :( '3', 'rw_words', 65536, "WORD", 16 , "Q", "W", "Holding Register"), + "04 - Input Registers" : ( '4', 'ro_words', 65536, "WORD", 16 , "I", "W", "Input Register"), + } + +class _MemoryAreaPlug: + XSD = """ + + + + + + + + + + + + + + + + + + + + + + + + """ + + def GetParamsAttributes(self, path = None): + infos = ConfigTreeNode.GetParamsAttributes(self, path = path) + for element in infos: + if element["name"] == "MemoryArea": + for child in element["children"]: + if child["name"] == "MemoryAreaType": + list = modbus_memtype_dict.keys() + list.sort() + child["type"] = list + return infos + + def GetVariableLocationTree(self): + current_location = self.GetCurrentLocation() + name = self.BaseParams.getName() + address = self.GetParamsAttributes()[0]["children"][2]["value"] + count = self.GetParamsAttributes()[0]["children"][1]["value"] + function= self.GetParamsAttributes()[0]["children"][0]["value"] + # 'BOOL' or 'WORD' + datatype= modbus_memtype_dict[function][3] + # 1 or 16 + datasize= modbus_memtype_dict[function][4] + # 'Q' for coils and holding registers, 'I' for input discretes and input registers + datazone= modbus_memtype_dict[function][5] + # 'X' for bits, 'W' for words + datatacc= modbus_memtype_dict[function][6] + # 'Coil', 'Holding Register', 'Input Discrete' or 'Input Register' + dataname= modbus_memtype_dict[function][7] + entries = [] + for offset in range(address, address+count): + entries.append({ + "name": dataname + " " + str(offset), + "type": LOCATION_VAR_MEMORY, + "size": datasize, + "IEC_type": datatype, + "var_name": "var_name", + "location": datatacc + ".".join([str(i) for i in current_location]) + "." + str(offset), + "description": "description", + "children": []}) + return {"name": name, + "type": LOCATION_CONFNODE, + "location": ".".join([str(i) for i in current_location]) + ".x", + "children": entries} + + def CTNGenerate_C(self, buildpath, locations): + """ + Generate C code + @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5) + @param locations: List of complete variables locations \ + [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...) + "NAME" : name of the variable (generally "__IW0_1_2" style) + "DIR" : direction "Q","I" or "M" + "SIZE" : size "X", "B", "W", "D", "L" + "LOC" : tuple of interger for IEC location (0,1,2,...) + }, ...] + @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND + """ + return [], "", False + + +################################################### +################################################### +# # +# T C P C L I E N T # +# # +################################################### +################################################### + +class _ModbusTCPclientPlug: + XSD = """ + + + + + + + + + + + + + + + + + """ + # NOTE: Max value of 2147483647 (i32_max) for Invocation_Rate_in_ms corresponds to aprox 25 days. + CTNChildrenTypes = [("ModbusRequest",_RequestPlug, "Request")] + # TODO: Replace with CTNType !!! + PlugType = "ModbusTCPclient" + + # Return the number of (modbus library) nodes this specific TCP client will need + # return type: (tcp nodes, rtu nodes, ascii nodes) + def GetNodeCount(self): + return (1, 0, 0) + + def CTNGenerate_C(self, buildpath, locations): + """ + Generate C code + @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5) + @param locations: List of complete variables locations \ + [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...) + "NAME" : name of the variable (generally "__IW0_1_2" style) + "DIR" : direction "Q","I" or "M" + "SIZE" : size "X", "B", "W", "D", "L" + "LOC" : tuple of interger for IEC location (0,1,2,...) + }, ...] + @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND + """ + return [], "", False + + + + +################################################### +################################################### +# # +# T C P S E R V E R # +# # +################################################### +################################################### + +class _ModbusTCPserverPlug: + # NOTE: the Port number is a 'string' and not an 'integer'! + # This is because the underlying modbus library accepts strings + # (e.g.: well known port names!) + XSD = """ + + + + + + + + + + + + + + + + + """ + CTNChildrenTypes = [("MemoryArea",_MemoryAreaPlug, "Memory Area")] + # TODO: Replace with CTNType !!! + PlugType = "ModbusTCPserver" + + # Return the number of (modbus library) nodes this specific TCP server will need + # return type: (tcp nodes, rtu nodes, ascii nodes) + def GetNodeCount(self): + return (1, 0, 0) + + # Return a list with a single tuple conatining the (location, port number) + # location: location of this node in the configuration tree + # port number: IP port used by this Modbus/IP server + def GetIPServerPortNumbers(self): + port = self.GetParamsAttributes()[0]["children"][1]["value"] + return [(self.GetCurrentLocation() , port)] + + def CTNGenerate_C(self, buildpath, locations): + """ + Generate C code + @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5) + @param locations: List of complete variables locations \ + [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...) + "NAME" : name of the variable (generally "__IW0_1_2" style) + "DIR" : direction "Q","I" or "M" + "SIZE" : size "X", "B", "W", "D", "L" + "LOC" : tuple of interger for IEC location (0,1,2,...) + }, ...] + @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND + """ + return [], "", False + + + + +################################################### +################################################### +# # +# R T U C L I E N T # +# # +################################################### +################################################### + +class _ModbusRTUclientPlug: + XSD = """ + + + + + + + + + + + + + + + + + + + """ + # NOTE: Max value of 2147483647 (i32_max) for Invocation_Rate_in_ms corresponds to aprox 25 days. + CTNChildrenTypes = [("ModbusRequest",_RequestPlug, "Request")] + # TODO: Replace with CTNType !!! + PlugType = "ModbusRTUclient" + + def GetParamsAttributes(self, path = None): + infos = ConfigTreeNode.GetParamsAttributes(self, path = path) + for element in infos: + if element["name"] == "ModbusRTUclient": + for child in element["children"]: + if child["name"] == "Baud_Rate": + child["type"] = modbus_serial_baudrate_list + if child["name"] == "Stop_Bits": + child["type"] = modbus_serial_stopbits_list + if child["name"] == "Parity": + child["type"] = modbus_serial_parity_dict.keys() + return infos + + # Return the number of (modbus library) nodes this specific RTU client will need + # return type: (tcp nodes, rtu nodes, ascii nodes) + def GetNodeCount(self): + return (0, 1, 0) + + def CTNGenerate_C(self, buildpath, locations): + """ + Generate C code + @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5) + @param locations: List of complete variables locations \ + [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...) + "NAME" : name of the variable (generally "__IW0_1_2" style) + "DIR" : direction "Q","I" or "M" + "SIZE" : size "X", "B", "W", "D", "L" + "LOC" : tuple of interger for IEC location (0,1,2,...) + }, ...] + @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND + """ + return [], "", False + + + +################################################### +################################################### +# # +# R T U S L A V E # +# # +################################################### +################################################### + + +class _ModbusRTUslavePlug: + XSD = """ + + + + + + + + + + + + + + + + + + + """ + CTNChildrenTypes = [("MemoryArea",_MemoryAreaPlug, "Memory Area")] + # TODO: Replace with CTNType !!! + PlugType = "ModbusRTUslave" + + def GetParamsAttributes(self, path = None): + infos = ConfigTreeNode.GetParamsAttributes(self, path = path) + for element in infos: + if element["name"] == "ModbusRTUslave": + for child in element["children"]: + if child["name"] == "Baud_Rate": + child["type"] = modbus_serial_baudrate_list + if child["name"] == "Stop_Bits": + child["type"] = modbus_serial_stopbits_list + if child["name"] == "Parity": + child["type"] = modbus_serial_parity_dict.keys() + return infos + + # Return the number of (modbus library) nodes this specific RTU slave will need + # return type: (tcp nodes, rtu nodes, ascii nodes) + def GetNodeCount(self): + return (0, 1, 0) + + def CTNGenerate_C(self, buildpath, locations): + """ + Generate C code + @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5) + @param locations: List of complete variables locations \ + [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...) + "NAME" : name of the variable (generally "__IW0_1_2" style) + "DIR" : direction "Q","I" or "M" + "SIZE" : size "X", "B", "W", "D", "L" + "LOC" : tuple of interger for IEC location (0,1,2,...) + }, ...] + @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND + """ + return [], "", False + + + +################################################### +################################################### +# # +# R O O T C L A S S # +# # +################################################### +################################################### +class RootClass: + XSD = """ + + + + + + + + + + + + + + + """ + CTNChildrenTypes = [("ModbusTCPclient",_ModbusTCPclientPlug, "Modbus TCP Client") + ,("ModbusTCPserver",_ModbusTCPserverPlug, "Modbus TCP Server") + ,("ModbusRTUclient",_ModbusRTUclientPlug, "Modbus RTU Client") + ,("ModbusRTUslave", _ModbusRTUslavePlug, "Modbus RTU Slave") + ] + + # Return the number of (modbus library) nodes this specific instance of the modbus plugin will need + # return type: (tcp nodes, rtu nodes, ascii nodes) + def GetNodeCount(self): + max_remote_tcpclient = self.GetParamsAttributes()[0]["children"][0]["value"] + total_node_count = (max_remote_tcpclient, 0, 0) + for child in self.IECSortedChildren(): + # ask each child how many nodes it needs, and add them all up. + total_node_count = tuple(x1 + x2 for x1, x2 in zip(total_node_count, child.GetNodeCount())) + return total_node_count + + # Return a list with tuples of the (location, port numbers) used by all the Modbus/IP servers + def GetIPServerPortNumbers(self): + IPServer_port_numbers = [] + for child in self.IECSortedChildren(): + if child.CTNType == "ModbusTCPserver": + IPServer_port_numbers.extend(child.GetIPServerPortNumbers()) + return IPServer_port_numbers + + def CTNGenerate_C(self, buildpath, locations): + #print "#############" + #print self.__class__ + #print type(self) + #print "self.CTNType >>>" + #print self.CTNType + #print "type(self.CTNType) >>>" + #print type(self.CTNType) + #print "#############" + + loc_dict = {"locstr" : "_".join(map(str,self.GetCurrentLocation())), + } + + # Determine the number of (modbus library) nodes ALL instances of the modbus plugin will need + # total_node_count: (tcp nodes, rtu nodes, ascii nodes) + # Also get a list with tuples of (location, IP port numbers) used by all the Modbus/IP server nodes + # This list is later used to search for duplicates in port numbers! + # IPServer_port_numbers = [(location ,IPserver_port_number), ...] + # location: tuple similar to (0, 3, 1) representing the location in the configuration tree "0.3.1.x" + # IPserver_port_number: a number (i.e. port number used by the Modbus/IP server) + total_node_count = (0, 0, 0) + IPServer_port_numbers = [] + for CTNInstance in self.GetCTRoot().IterChildren(): + if CTNInstance.CTNType == "modbus": + # ask each modbus plugin instance how many nodes it needs, and add them all up. + total_node_count = tuple(x1 + x2 for x1, x2 in zip(total_node_count, CTNInstance.GetNodeCount())) + IPServer_port_numbers.extend(CTNInstance.GetIPServerPortNumbers()) + + # Search for use of duplicate port numbers by Modbus/IP servers + #print IPServer_port_numbers + # ..but first define a lambda function to convert a tuple with the config tree location to a nice looking string + # for e.g., convert the tuple (0, 3, 4) to "0.3.4" + lt_to_str = lambda loctuple: '.'.join(map(str, loctuple)) + for i in range(0, len(IPServer_port_numbers)-1): + for j in range (i+1, len(IPServer_port_numbers)): + if IPServer_port_numbers[i][1] == IPServer_port_numbers[j][1]: + 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])) + raise Exception, False + # TODO: return an error code instead of raising an exception + + # Determine the current location in Beremiz's project configuration tree + current_location = self.GetCurrentLocation() + + # define a unique name for the generated C and h files + prefix = "_".join(map(str, current_location)) + Gen_MB_c_path = os.path.join(buildpath, "MB_%s.c"%prefix) + Gen_MB_h_path = os.path.join(buildpath, "MB_%s.h"%prefix) + c_filename = os.path.join(os.path.split(__file__)[0],"mb_runtime.c") + h_filename = os.path.join(os.path.split(__file__)[0],"mb_runtime.h") + + tcpclient_reqs_count = 0 + rtuclient_reqs_count = 0 + ascclient_reqs_count = 0 + tcpclient_node_count = 0 + rtuclient_node_count = 0 + ascclient_node_count = 0 + tcpserver_node_count = 0 + rtuserver_node_count = 0 + ascserver_node_count = 0 + nodeid = 0 + client_nodeid = 0 + client_requestid = 0 + server_id = 0 + + server_node_list = [] + client_node_list = [] + client_request_list = [] + server_memarea_list = [] + loc_vars = [] + loc_vars_list = [] # list of variables already declared in C code! + for child in self.IECSortedChildren(): + #print "<<<<<<<<<<<<<" + #print "child (self.IECSortedChildren())----->" + #print child.__class__ + #print ">>>>>>>>>>>>>" + ###################################### + if child.PlugType == "ModbusTCPserver": + tcpserver_node_count += 1 + new_node = GetTCPServerNodePrinted(self, child) + if new_node is None: + return [],"",False + server_node_list.append(new_node) + ############## + for subchild in child.IECSortedChildren(): + new_memarea = GetTCPServerMemAreaPrinted(self, subchild, nodeid) + if new_memarea is None: + return [],"",False + server_memarea_list.append(new_memarea) + function= subchild.GetParamsAttributes()[0]["children"][0]["value"] + # 'ro_bits', 'rw_bits', 'ro_words' or 'rw_words' + memarea= modbus_memtype_dict[function][1] + for iecvar in subchild.GetLocations(): + #print repr(iecvar) + absloute_address = iecvar["LOC"][3] + start_address = int(subchild.GetParamsAttributes()[0]["children"][2]["value"]) + relative_addr = absloute_address - start_address + #test if relative address in request specified range + if relative_addr in xrange(int(subchild.GetParamsAttributes()[0]["children"][1]["value"])): + if str(iecvar["NAME"]) not in loc_vars_list: + loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.%s[%d];" % (server_id, memarea, absloute_address)) + loc_vars_list.append(str(iecvar["NAME"])) + server_id += 1 + ###################################### + if child.PlugType == "ModbusRTUslave": + rtuserver_node_count += 1 + new_node = GetRTUSlaveNodePrinted(self, child) + if new_node is None: + return [],"",False + server_node_list.append(new_node) + ############## + for subchild in child.IECSortedChildren(): + new_memarea = GetTCPServerMemAreaPrinted(self, subchild, nodeid) + if new_memarea is None: + return [],"",False + server_memarea_list.append(new_memarea) + function= subchild.GetParamsAttributes()[0]["children"][0]["value"] + # 'ro_bits', 'rw_bits', 'ro_words' or 'rw_words' + memarea= modbus_memtype_dict[function][1] + for iecvar in subchild.GetLocations(): + #print repr(iecvar) + absloute_address = iecvar["LOC"][3] + start_address = int(subchild.GetParamsAttributes()[0]["children"][2]["value"]) + relative_addr = absloute_address - start_address + #test if relative address in request specified range + if relative_addr in xrange(int(subchild.GetParamsAttributes()[0]["children"][1]["value"])): + if str(iecvar["NAME"]) not in loc_vars_list: + loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.%s[%d];" % (server_id, memarea, absloute_address)) + loc_vars_list.append(str(iecvar["NAME"])) + server_id += 1 + ###################################### + if child.PlugType == "ModbusTCPclient": + tcpclient_reqs_count += len(child.IECSortedChildren()) + new_node = GetTCPClientNodePrinted(self, child) + if new_node is None: + return [],"",False + client_node_list.append(new_node) + for subchild in child.IECSortedChildren(): + new_req = GetClientRequestPrinted(self, subchild, client_nodeid) + if new_req is None: + return [],"",False + client_request_list.append(new_req) + for iecvar in subchild.GetLocations(): + #absloute address - start address + relative_addr = iecvar["LOC"][3] - int(subchild.GetParamsAttributes()[0]["children"][3]["value"]) + #test if relative address in request specified range + if relative_addr in xrange(int(subchild.GetParamsAttributes()[0]["children"][2]["value"])): + if str(iecvar["NAME"]) not in loc_vars_list: + loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &client_requests[%d].plcv_buffer[%d];" % (client_requestid, relative_addr)) + loc_vars_list.append(str(iecvar["NAME"])) + client_requestid += 1 + tcpclient_node_count += 1 + client_nodeid += 1 + ###################################### + if child.PlugType == "ModbusRTUclient": + rtuclient_reqs_count += len(child.IECSortedChildren()) + new_node = GetRTUClientNodePrinted(self, child) + if new_node is None: + return [],"",False + client_node_list.append(new_node) + for subchild in child.IECSortedChildren(): + new_req = GetClientRequestPrinted(self, subchild, client_nodeid) + if new_req is None: + return [],"",False + client_request_list.append(new_req) + for iecvar in subchild.GetLocations(): + #absloute address - start address + relative_addr = iecvar["LOC"][3] - int(subchild.GetParamsAttributes()[0]["children"][3]["value"]) + #test if relative address in request specified range + if relative_addr in xrange(int(subchild.GetParamsAttributes()[0]["children"][2]["value"])): + if str(iecvar["NAME"]) not in loc_vars_list: + loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &client_requests[%d].plcv_buffer[%d];" % (client_requestid, relative_addr)) + loc_vars_list.append(str(iecvar["NAME"])) + client_requestid += 1 + rtuclient_node_count += 1 + client_nodeid += 1 + nodeid += 1 + + loc_dict["loc_vars"] = "\n".join(loc_vars) + loc_dict["server_nodes_params"] = ",\n\n".join(server_node_list) + loc_dict["client_nodes_params"] = ",\n\n".join(client_node_list) + loc_dict["client_req_params"] = ",\n\n".join(client_request_list) + loc_dict["tcpclient_reqs_count"] = str(tcpclient_reqs_count) + loc_dict["tcpclient_node_count"] = str(tcpclient_node_count) + loc_dict["tcpserver_node_count"] = str(tcpserver_node_count) + loc_dict["rtuclient_reqs_count"] = str(rtuclient_reqs_count) + loc_dict["rtuclient_node_count"] = str(rtuclient_node_count) + loc_dict["rtuserver_node_count"] = str(rtuserver_node_count) + loc_dict["ascclient_reqs_count"] = str(ascclient_reqs_count) + loc_dict["ascclient_node_count"] = str(ascclient_node_count) + loc_dict["ascserver_node_count"] = str(ascserver_node_count) + loc_dict["total_tcpnode_count"] = str(total_node_count[0]) + loc_dict["total_rtunode_count"] = str(total_node_count[1]) + loc_dict["total_ascnode_count"] = str(total_node_count[2]) + loc_dict["max_remote_tcpclient"] = int(self.GetParamsAttributes()[0]["children"][0]["value"]) + + #get template file content into a string, format it with dict + #and write it to proper .h file + mb_main = open(h_filename).read() % loc_dict + f = open(Gen_MB_h_path,'w') + f.write(mb_main) + f.close() + #same thing as above, but now to .c file + mb_main = open(c_filename).read() % loc_dict + f = open(Gen_MB_c_path,'w') + f.write(mb_main) + f.close() + + LDFLAGS = [] + LDFLAGS.append(" \"-L" + ModbusPath + "\"") + LDFLAGS.append(" -lmb ") + LDFLAGS.append(" \"-Wl,-rpath," + ModbusPath + "\"") + #LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_slave_and_master.o") + "\"") + #LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_slave.o") + "\"") + #LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_master.o") + "\"") + #LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_tcp.o") + "\"") + #LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_rtu.o") + "\"") + #LDFLAGS.append("\"" + os.path.join(ModbusPath, "mb_ascii.o") + "\"") + #LDFLAGS.append("\"" + os.path.join(ModbusPath, "sin_util.o") + "\"") + if os.name == 'nt': # other possible values: 'posix' 'os2' 'ce' 'java' 'riscos' + LDFLAGS.append(" -lws2_32 ") # on windows we need to load winsock library! + + return [(Gen_MB_c_path, ' -I"'+ModbusPath+'"')], LDFLAGS, True