--- a/modbus/mb_utils.py Wed Jan 31 15:22:43 2018 +0100
+++ b/modbus/mb_utils.py Wed Jan 31 15:25:30 2018 +0100
@@ -18,27 +18,35 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# This code is made available on the understanding that it will not be
# used in safety-critical situations without a full and competent review.
+# dictionary implementing: +# key - string with the description we want in the request plugin GUI +# tuple - (modbus function number, request type, max count value, +modbus_function_dict = { + "01 - Read Coils": ('1', 'req_input', 2000, "BOOL", 1, "Q", "X", "Coil"), + "02 - Read Input Discretes": ('2', 'req_input', 2000, "BOOL", 1, "I", "X", "Input Discrete"), + "03 - Read Holding Registers": ('3', 'req_input', 125, "WORD", 16, "Q", "W", "Holding Register"), + "04 - Read Input Registers": ('4', 'req_input', 125, "WORD", 16, "I", "W", "Input Register"), + "05 - Write Single coil": ('5', 'req_output', 1, "BOOL", 1, "Q", "X", "Coil"), + "06 - Write Single Register": ('6', 'req_output', 1, "WORD", 16, "Q", "W", "Holding Register"), + "15 - Write Multiple Coils": ('15', 'req_output', 1968, "BOOL", 1, "Q", "X", "Coil"), + "16 - Write Multiple Registers": ('16', 'req_output', 123, "WORD", 16, "Q", "W", "Holding Register")} -#dictionary implementing:
-#key - string with the description we want in the request plugin GUI
-#tuple - (modbus function number, request type, max count value, data_type, bit_size)
-modbus_function_dict = {"01 - Read Coils" : ( '1', 'req_input', 2000, "BOOL", 1 , "Q", "X", "Coil"),
- "02 - Read Input Discretes" : ( '2', 'req_input', 2000, "BOOL", 1 , "I", "X", "Input Discrete"),
- "03 - Read Holding Registers" : ( '3', 'req_input', 125, "WORD", 16, "Q", "W", "Holding Register"),
- "04 - Read Input Registers" : ( '4', 'req_input', 125, "WORD", 16, "I", "W", "Input Register"),
- "05 - Write Single coil" : ( '5','req_output', 1, "BOOL", 1 , "Q", "X", "Coil"),
- "06 - Write Single Register" : ( '6','req_output', 1, "WORD", 16, "Q", "W", "Holding Register"),
- "15 - Write Multiple Coils" : ('15','req_output', 1968, "BOOL", 1 , "Q", "X", "Coil"),
- "16 - Write Multiple Registers" : ('16','req_output', 123, "WORD", 16, "Q", "W", "Holding Register"),
+# Configuration tree value acces helper +def GetCTVal(child, index): + return child.GetParamsAttributes()[0]["children"][index]["value"] +# Configuration tree value acces helper, for multiple values +def GetCTVals(child, indexes): + return map(lambda index: GetCTVal(child, index), indexes) def GetTCPServerNodePrinted(self, child):
@@ -49,28 +57,24 @@
{"%(locnodestr)s", %(slaveid)s, {naf_tcp, {.tcp = {%(host)s, "%(port)s", DEF_CLOSE_ON_SILENCE}}}, -1 /* mb_nd */, 0 /* init_state */}'''
location = ".".join(map(str, child.GetCurrentLocation()))
- host = child.GetParamsAttributes()[0]["children"][0]["value"]
- port = child.GetParamsAttributes()[0]["children"][1]["value"]
- slaveid = child.GetParamsAttributes()[0]["children"][2]["value"]
+ host, port, slaveid = GetCTVals(child, range(3))
- #slaveid = child.GetParamsAttributes()[0]["children"][2]["value"]
- #if int(slaveid) not in xrange(256):
- #self.GetCTRoot().logger.write_error("Error: Wrong slave ID in %s server node\nModbus Plugin C code returns empty\n"%location)
+ host = '"' + host + '"' + # slaveid = GetCTVal(child, 2) + # if int(slaveid) not in xrange(256): + # self.GetCTRoot().logger.write_error("Error: Wrong slave ID in %s server node\nModbus Plugin C code returns empty\n"%location) - node_dict = {"locnodestr" : location,
+ node_dict = {"locnodestr": location, return node_init_template % node_dict
def GetTCPServerMemAreaPrinted(self, child, nodeid):
Outputs a string to be used on C files
@@ -84,27 +88,28 @@
request_dict["locreqstr"] = "_".join(map(str, child.GetCurrentLocation()))
request_dict["nodeid"] = str(nodeid)
- request_dict["address"] = child.GetParamsAttributes()[0]["children"][2]["value"]
+ request_dict["address"] = GetCTVal(child, 2) if int(request_dict["address"]) not in xrange(65536):
- self.GetCTRoot().logger.write_error("Modbus plugin: Invalid Start Address in server memory area node %(locreqstr)s (Must be in the range [0..65535])\nModbus plugin: Aborting C code generation for this node\n"%request_dict)
+ self.GetCTRoot().logger.write_error( + "Modbus plugin: Invalid Start Address in server memory area node %(locreqstr)s (Must be in the range [0..65535])\nModbus plugin: Aborting C code generation for this node\n" % request_dict) - request_dict["count"] = child.GetParamsAttributes()[0]["children"][1]["value"]
+ request_dict["count"] = GetCTVal(child, 1) if int(request_dict["count"]) not in xrange(1, 65536):
- self.GetCTRoot().logger.write_error("Modbus plugin: Invalid number of channels in server memory area node %(locreqstr)s (Must be in the range [1..65536-start_address])\nModbus plugin: Aborting C code generation for this node\n"%request_dict)
+ self.GetCTRoot().logger.write_error( + "Modbus plugin: Invalid number of channels in server memory area node %(locreqstr)s (Must be in the range [1..65536-start_address])\nModbus plugin: Aborting C code generation for this node\n" % request_dict) - if (int(request_dict["address"]) + int(request_dict["count"])) not in xrange(1,65537):
- self.GetCTRoot().logger.write_error("Modbus plugin: Invalid number of channels in server memory area node %(locreqstr)s (Must be in the range [1..65536-start_address])\nModbus plugin: Aborting C code generation for this node\n"%request_dict)
+ if (int(request_dict["address"]) + int(request_dict["count"])) not in xrange(1, 65537): + self.GetCTRoot().logger.write_error( + "Modbus plugin: Invalid number of channels in server memory area node %(locreqstr)s (Must be in the range [1..65536-start_address])\nModbus plugin: Aborting C code generation for this node\n" % request_dict)
-modbus_serial_baudrate_list = ["110", "300", "600", "1200", "2400", "4800", "9600", "19200", "38400", "57600", "115200"]
+modbus_serial_baudrate_list = [ + "110", "300", "600", "1200", "2400", "4800", "9600", "19200", "38400", "57600", "115200"] modbus_serial_stopbits_list = ["1", "2"]
-modbus_serial_parity_dict = {"none": 0, "odd": 1, "even": 2}
+modbus_serial_parity_dict = {"none": 0, "odd": 1, "even": 2} def GetRTUSlaveNodePrinted(self, child):
@@ -116,25 +121,18 @@
{"%(locnodestr)s", %(slaveid)s, {naf_rtu, {.rtu = {"%(device)s", %(baud)s /*baud*/, %(parity)s /*parity*/, 8 /*data bits*/, %(stopbits)s, 0 /* ignore echo */}}}, -1 /* mb_nd */, 0 /* init_state */}'''
location = ".".join(map(str, child.GetCurrentLocation()))
- device = child.GetParamsAttributes()[0]["children"][0]["value"]
- baud = child.GetParamsAttributes()[0]["children"][1]["value"]
- parity = child.GetParamsAttributes()[0]["children"][2]["value"]
- stopbits = child.GetParamsAttributes()[0]["children"][3]["value"]
- slaveid = child.GetParamsAttributes()[0]["children"][4]["value"]
- node_dict = {"locnodestr" : location,
- "parity" : modbus_serial_parity_dict[parity],
+ device, baud, parity, stopbits, slaveid = GetCTVals(child, range(5)) + node_dict = {"locnodestr": location, + "parity": modbus_serial_parity_dict[parity], return node_init_template % node_dict
def GetRTUClientNodePrinted(self, child):
Outputs a string to be used on C files
@@ -143,25 +141,19 @@
node_init_template = '''/*node %(locnodestr)s*/
{"%(locnodestr)s", {naf_rtu, {.rtu = {"%(device)s", %(baud)s /*baud*/, %(parity)s /*parity*/, 8 /*data bits*/, %(stopbits)s, 0 /* ignore echo */}}}, -1 /* mb_nd */, 0 /* init_state */, %(coms_period)s /* communication period */}'''
- location = ".".join(map(str, child.GetCurrentLocation()))
- device = child.GetParamsAttributes()[0]["children"][0]["value"]
- baud = child.GetParamsAttributes()[0]["children"][1]["value"]
- parity = child.GetParamsAttributes()[0]["children"][2]["value"]
- stopbits = child.GetParamsAttributes()[0]["children"][3]["value"]
- coms_period = child.GetParamsAttributes()[0]["children"][4]["value"]
- node_dict = {"locnodestr" : location,
- "parity" : modbus_serial_parity_dict[parity],
- "coms_period" : coms_period
+ location = ".".join(map(str, child.GetCurrentLocation())) + device, baud, parity, stopbits, coms_period = GetCTVals(child, range(5)) + node_dict = {"locnodestr": location, + "parity": modbus_serial_parity_dict[parity], + "coms_period": coms_period return node_init_template % node_dict
def GetTCPClientNodePrinted(self, child):
Outputs a string to be used on C files
@@ -171,20 +163,16 @@
{"%(locnodestr)s", {naf_tcp, {.tcp = {"%(host)s", "%(port)s", DEF_CLOSE_ON_SILENCE}}}, -1 /* mb_nd */, 0 /* init_state */, %(coms_period)s /* communication period */, 0 /* prev_error */}'''
location = ".".join(map(str, child.GetCurrentLocation()))
- host = child.GetParamsAttributes()[0]["children"][0]["value"]
- port = child.GetParamsAttributes()[0]["children"][1]["value"]
- coms_period = child.GetParamsAttributes()[0]["children"][2]["value"]
+ host, port, coms_period = GetCTVals(child, range(3)) - node_dict = {"locnodestr" : location,
- "coms_period" : coms_period
+ node_dict = {"locnodestr": location, + "coms_period": coms_period return node_init_template % node_dict
def GetClientRequestPrinted(self, child, nodeid):
Outputs a string to be used on C files
@@ -199,38 +187,41 @@
{"%(locreqstr)s", %(nodeid)s, %(slaveid)s, %(iotype)s, %(func_nr)s, %(address)s , %(count)s,
DEF_REQ_SEND_RETRIES, 0 /* error_code */, 0 /* prev_code */, {%(timeout_s)d, %(timeout_ns)d} /* timeout */,
{%(buffer)s}, {%(buffer)s}}'''
- timeout = int(child.GetParamsAttributes()[0]["children"][4]["value"])
- timeout_s = int(timeout / 1000)
- timeout_ms = timeout - (timeout_s * 1000)
- timeout_ns = timeout_ms * 1000000
+ timeout = int(GetCTVal(child, 4)) + timeout_s = int(timeout / 1000) + timeout_ms = timeout - (timeout_s * 1000) + timeout_ns = timeout_ms * 1000000 - request_dict["locreqstr" ] = "_".join(map(str, child.GetCurrentLocation()))
- request_dict["nodeid" ] = str(nodeid)
- request_dict["slaveid" ] = child.GetParamsAttributes()[0]["children"][1]["value"]
- request_dict["address" ] = child.GetParamsAttributes()[0]["children"][3]["value"]
- request_dict["count" ] = child.GetParamsAttributes()[0]["children"][2]["value"]
- request_dict["timeout" ] = timeout
- request_dict["timeout_s" ] = timeout_s
- request_dict["timeout_ns"] = timeout_ns
- request_dict["buffer" ] = ",".join(['0'] * int(child.GetParamsAttributes()[0]["children"][2]["value"]))
- request_dict["func_nr" ] = modbus_function_dict[child.GetParamsAttributes()[0]["children"][0]["value"]][0]
- request_dict["iotype" ] = modbus_function_dict[child.GetParamsAttributes()[0]["children"][0]["value"]][1]
- request_dict["maxcount" ] = modbus_function_dict[child.GetParamsAttributes()[0]["children"][0]["value"]][2]
+ "locreqstr": "_".join(map(str, child.GetCurrentLocation())), + "slaveid": GetCTVal(child, 1), + "address": GetCTVal(child, 3), + "count": GetCTVal(child, 2), + "timeout_s": timeout_s, + "timeout_ns": timeout_ns, + "buffer": ",".join(['0'] * int(GetCTVal(child, 2))), + "func_nr": modbus_function_dict[GetCTVal(child, 0)][0], + "iotype": modbus_function_dict[GetCTVal(child, 0)][1], + "maxcount": modbus_function_dict[GetCTVal(child, 0)][2]} if int(request_dict["slaveid"]) not in xrange(256):
- self.GetCTRoot().logger.write_error("Modbus plugin: Invalid slaveID in TCP client request node %(locreqstr)s (Must be in the range [0..255])\nModbus plugin: Aborting C code generation for this node\n"%request_dict)
+ self.GetCTRoot().logger.write_error( + "Modbus plugin: Invalid slaveID in TCP client request node %(locreqstr)s (Must be in the range [0..255])\nModbus plugin: Aborting C code generation for this node\n" % request_dict) if int(request_dict["address"]) not in xrange(65536):
- self.GetCTRoot().logger.write_error("Modbus plugin: Invalid Start Address in TCP client request node %(locreqstr)s (Must be in the range [0..65535])\nModbus plugin: Aborting C code generation for this node\n"%request_dict)
+ self.GetCTRoot().logger.write_error( + "Modbus plugin: Invalid Start Address in TCP client request node %(locreqstr)s (Must be in the range [0..65535])\nModbus plugin: Aborting C code generation for this node\n" % request_dict) - if int(request_dict["count"]) not in xrange(1, 1+int(request_dict["maxcount"])):
- self.GetCTRoot().logger.write_error("Modbus plugin: Invalid number of channels in TCP client request node %(locreqstr)s (Must be in the range [1..%(maxcount)s])\nModbus plugin: Aborting C code generation for this node\n"%request_dict)
+ if int(request_dict["count"]) not in xrange(1, 1 + int(request_dict["maxcount"])): + self.GetCTRoot().logger.write_error( + "Modbus plugin: Invalid number of channels in TCP client request node %(locreqstr)s (Must be in the range [1..%(maxcount)s])\nModbus plugin: Aborting C code generation for this node\n" % request_dict) - if (int(request_dict["address"]) + int(request_dict["count"])) not in xrange(1,65537):
- self.GetCTRoot().logger.write_error("Modbus plugin: Invalid number of channels in TCP client request node %(locreqstr)s (start_address + nr_channels must be less than 65536)\nModbus plugin: Aborting C code generation for this node\n"%request_dict)
+ if (int(request_dict["address"]) + int(request_dict["count"])) not in xrange(1, 65537): + self.GetCTRoot().logger.write_error( + "Modbus plugin: Invalid number of channels in TCP client request node %(locreqstr)s (start_address + nr_channels must be less than 65536)\nModbus plugin: Aborting C code generation for this node\n" % request_dict)
return req_init_template % request_dict
--- a/modbus/modbus.py Wed Jan 31 15:22:43 2018 +0100
+++ b/modbus/modbus.py Wed Jan 31 15:25:30 2018 +0100
@@ -18,33 +18,31 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# This code is made available on the understanding that it will not be
# used in safety-critical situations without a full and competent review.
-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 ConfigTreeNode import ConfigTreeNode
from PLCControler import LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
+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") -###################################################
-###################################################
-# C L I E N T R E Q U E S T #
-###################################################
-###################################################
+# C L I E N T R E Q U E S T # @@ -90,8 +88,8 @@
- def GetParamsAttributes(self, path = None):
- infos = ConfigTreeNode.GetParamsAttributes(self, path = path)
+ def GetParamsAttributes(self, path=None): + infos = ConfigTreeNode.GetParamsAttributes(self, path=path) if element["name"] == "ModbusRequest":
for child in element["children"]:
@@ -100,25 +98,25 @@
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"]
+ count = self.GetParamsAttributes()[0]["children"][2]["value"] + function = self.GetParamsAttributes()[0]["children"][0]["value"] - datatype= modbus_function_dict[function][3]
+ datatype = modbus_function_dict[function][3] - datasize= modbus_function_dict[function][4]
+ 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]
+ datazone = modbus_function_dict[function][5] # 'X' for bits, 'W' for words
- datatacc= modbus_function_dict[function][6]
+ datatacc = modbus_function_dict[function][6] # 'Coil', 'Holding Register', 'Input Discrete' or 'Input Register'
- dataname= modbus_function_dict[function][7]
+ dataname = modbus_function_dict[function][7] - for offset in range(address, address+count):
+ for offset in range(address, address + count): "name": dataname + " " + str(offset),
"type": LOCATION_VAR_MEMORY,
@@ -128,14 +126,10 @@
"location": datatacc + ".".join([str(i) for i in current_location]) + "." + str(offset),
"description": "description",
- "type": LOCATION_CONFNODE,
- "location": ".".join([str(i) for i in current_location]) + ".x",
+ "type": LOCATION_CONFNODE, + "location": ".".join([str(i) for i in current_location]) + ".x", def CTNGenerate_C(self, buildpath, locations):
@@ -151,24 +145,26 @@
@return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
-###################################################
-###################################################
-# S E R V E R M E M O R Y A R E A #
-###################################################
-###################################################
+# 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"),
+# dictionary implementing: +# key - string with the description we want in the request plugin GUI +# list - (modbus function number, request type, max count value) + "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"), XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
@@ -197,8 +193,8 @@
- def GetParamsAttributes(self, path = None):
- infos = ConfigTreeNode.GetParamsAttributes(self, path = path)
+ def GetParamsAttributes(self, path=None): + infos = ConfigTreeNode.GetParamsAttributes(self, path=path) if element["name"] == "MemoryArea":
for child in element["children"]:
@@ -212,20 +208,20 @@
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"]
+ count = self.GetParamsAttributes()[0]["children"][1]["value"] + function = self.GetParamsAttributes()[0]["children"][0]["value"] - datatype= modbus_memtype_dict[function][3]
+ datatype = modbus_memtype_dict[function][3] - datasize= modbus_memtype_dict[function][4]
+ 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]
+ datazone = modbus_memtype_dict[function][5] # 'X' for bits, 'W' for words
- datatacc= modbus_memtype_dict[function][6]
+ datatacc = modbus_memtype_dict[function][6] # 'Coil', 'Holding Register', 'Input Discrete' or 'Input Register'
- dataname= modbus_memtype_dict[function][7]
+ dataname = modbus_memtype_dict[function][7] - for offset in range(address, address+count):
+ for offset in range(address, address + count): "name": dataname + " " + str(offset),
"type": LOCATION_VAR_MEMORY,
@@ -235,10 +231,10 @@
"location": datatacc + ".".join([str(i) for i in current_location]) + "." + str(offset),
"description": "description",
- "type": LOCATION_CONFNODE,
- "location": ".".join([str(i) for i in current_location]) + ".x",
+ "type": LOCATION_CONFNODE, + "location": ".".join([str(i) for i in current_location]) + ".x", def CTNGenerate_C(self, buildpath, locations):
@@ -255,14 +251,14 @@
-###################################################
-###################################################
-###################################################
-###################################################
class _ModbusTCPclientPlug:
XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
@@ -283,8 +279,9 @@
- # NOTE: Max value of 2147483647 (i32_max) for Invocation_Rate_in_ms corresponds to aprox 25 days.
- CTNChildrenTypes = [("ModbusRequest",_RequestPlug, "Request")]
+ # 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"
@@ -309,19 +306,17 @@
-###################################################
-###################################################
-###################################################
-###################################################
class _ModbusTCPserverPlug:
# NOTE: the Port number is a 'string' and not an 'integer'!
- # This is because the underlying modbus library accepts strings
+ # This is because the underlying modbus library accepts strings # (e.g.: well known port names!)
XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
@@ -341,7 +336,7 @@
- CTNChildrenTypes = [("MemoryArea",_MemoryAreaPlug, "Memory Area")]
+ CTNChildrenTypes = [("MemoryArea", _MemoryAreaPlug, "Memory Area")] # TODO: Replace with CTNType !!!
PlugType = "ModbusTCPserver"
@@ -355,7 +350,7 @@
# port number: IP port used by this Modbus/IP server
def GetIPServerPortNumbers(self):
port = self.GetParamsAttributes()[0]["children"][1]["value"]
- return [(self.GetCurrentLocation() , port)]
+ return [(self.GetCurrentLocation(), port)] def CTNGenerate_C(self, buildpath, locations):
@@ -373,15 +368,13 @@
-###################################################
-###################################################
-###################################################
-###################################################
class _ModbusRTUclientPlug:
XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
@@ -404,13 +397,14 @@
- # NOTE: Max value of 2147483647 (i32_max) for Invocation_Rate_in_ms corresponds to aprox 25 days.
- CTNChildrenTypes = [("ModbusRequest",_RequestPlug, "Request")]
+ # 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)
+ def GetParamsAttributes(self, path=None): + infos = ConfigTreeNode.GetParamsAttributes(self, path=path) if element["name"] == "ModbusRTUclient":
for child in element["children"]:
@@ -421,7 +415,7 @@
if child["name"] == "Parity":
child["type"] = modbus_serial_parity_dict.keys()
# Return the number of (modbus library) nodes this specific RTU client will need
# return type: (tcp nodes, rtu nodes, ascii nodes)
@@ -443,14 +437,13 @@
-###################################################
-###################################################
-###################################################
-###################################################
class _ModbusRTUslavePlug:
@@ -474,12 +467,12 @@
- CTNChildrenTypes = [("MemoryArea",_MemoryAreaPlug, "Memory Area")]
+ CTNChildrenTypes = [("MemoryArea", _MemoryAreaPlug, "Memory Area")] # TODO: Replace with CTNType !!!
PlugType = "ModbusRTUslave"
- def GetParamsAttributes(self, path = None):
- infos = ConfigTreeNode.GetParamsAttributes(self, path = path)
+ def GetParamsAttributes(self, path=None): + infos = ConfigTreeNode.GetParamsAttributes(self, path=path) if element["name"] == "ModbusRTUslave":
for child in element["children"]:
@@ -490,7 +483,7 @@
if child["name"] == "Parity":
child["type"] = modbus_serial_parity_dict.keys()
# Return the number of (modbus library) nodes this specific RTU slave will need
# return type: (tcp nodes, rtu nodes, ascii nodes)
@@ -511,15 +504,18 @@
+def _lt_to_str(loctuple): + return '.'.join(map(str, loctuple)) -###################################################
-###################################################
-###################################################
-###################################################
XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
@@ -537,23 +533,23 @@
- CTNChildrenTypes = [("ModbusTCPclient",_ModbusTCPclientPlug, "Modbus TCP Client")
- ,("ModbusTCPserver",_ModbusTCPserverPlug, "Modbus TCP Server")
- ,("ModbusRTUclient",_ModbusRTUclientPlug, "Modbus RTU Client")
- ,("ModbusRTUslave", _ModbusRTUslavePlug, "Modbus RTU Slave")
+ 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)
- max_remote_tcpclient = self.GetParamsAttributes()[0]["children"][0]["value"]
+ 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()))
+ total_node_count = tuple( + x1 + x2 for x1, x2 in zip(total_node_count, child.GetNodeCount())) - # Return a list with tuples of the (location, port numbers) used by all the Modbus/IP servers
+ # 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():
@@ -562,54 +558,64 @@
return IPServer_port_numbers
def CTNGenerate_C(self, buildpath, locations):
- #print "self.CTNType >>>"
- #print "type(self.CTNType) >>>"
- #print type(self.CTNType)
- loc_dict = {"locstr" : "_".join(map(str,self.GetCurrentLocation())),
+ # print "#############" + # 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)
+ # IPserver_port_number: a number (i.e. port number used by the 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())
+ # ask each modbus plugin instance how many nodes it needs, and + 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
+ # 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)):
+ # for e.g., convert the tuple (0, 3, 4) to "0.3.4" + 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]))
- # TODO: return an error code instead of raising an exception
- # Determine the current location in Beremiz's project configuration tree
+ 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])) + # TODO: return an error code instead of raising an + # Determine the current location in Beremiz's project configuration 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")
+ 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") @@ -624,124 +630,134 @@
- loc_vars_list = [] # list of variables already declared in C code!
+ loc_vars_list = [] # list of variables already declared in C code! for child in self.IECSortedChildren():
- #print "child (self.IECSortedChildren())----->"
- ######################################
+ # print "<<<<<<<<<<<<<" + # print "child (self.IECSortedChildren())----->" + # print child.__class__ + # print ">>>>>>>>>>>>>" if child.PlugType == "ModbusTCPserver":
tcpserver_node_count += 1
new_node = GetTCPServerNodePrinted(self, child)
server_node_list.append(new_node)
for subchild in child.IECSortedChildren():
- new_memarea = GetTCPServerMemAreaPrinted(self, subchild, nodeid)
+ new_memarea = GetTCPServerMemAreaPrinted( + self, subchild, nodeid)
server_memarea_list.append(new_memarea)
- function= subchild.GetParamsAttributes()[0]["children"][0]["value"]
+ function = subchild.GetParamsAttributes()[ + 0]["children"][0]["value"] # 'ro_bits', 'rw_bits', 'ro_words' or 'rw_words'
- memarea= modbus_memtype_dict[function][1]
+ memarea = modbus_memtype_dict[function][1] for iecvar in subchild.GetLocations():
absloute_address = iecvar["LOC"][3]
- start_address = int(subchild.GetParamsAttributes()[0]["children"][2]["value"])
+ start_address = int(GetCTVal(child, 2)) 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"])):
+ # test if relative address in request specified range + if relative_addr in xrange(int(GetCTVal(child, 1))): 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.append("u16 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.%s[%d];" % ( + server_id, memarea, absloute_address)) loc_vars_list.append(str(iecvar["NAME"]))
- ######################################
if child.PlugType == "ModbusRTUslave":
rtuserver_node_count += 1
new_node = GetRTUSlaveNodePrinted(self, child)
server_node_list.append(new_node)
for subchild in child.IECSortedChildren():
- new_memarea = GetTCPServerMemAreaPrinted(self, subchild, nodeid)
+ new_memarea = GetTCPServerMemAreaPrinted( + self, subchild, nodeid)
server_memarea_list.append(new_memarea)
- function= subchild.GetParamsAttributes()[0]["children"][0]["value"]
+ function = subchild.GetParamsAttributes()[ + 0]["children"][0]["value"] # 'ro_bits', 'rw_bits', 'ro_words' or 'rw_words'
- memarea= modbus_memtype_dict[function][1]
+ memarea = modbus_memtype_dict[function][1] for iecvar in subchild.GetLocations():
absloute_address = iecvar["LOC"][3]
- start_address = int(subchild.GetParamsAttributes()[0]["children"][2]["value"])
+ start_address = int(GetCTVal(child, 2)) 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"])):
+ # test if relative address in request specified range + if relative_addr in xrange(int(GetCTVal(child, 1))): 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.append("u16 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.%s[%d];" % ( + server_id, memarea, absloute_address)) loc_vars_list.append(str(iecvar["NAME"]))
- ######################################
if child.PlugType == "ModbusTCPclient":
tcpclient_reqs_count += len(child.IECSortedChildren())
new_node = GetTCPClientNodePrinted(self, child)
client_node_list.append(new_node)
for subchild in child.IECSortedChildren():
- new_req = GetClientRequestPrinted(self, subchild, client_nodeid)
+ new_req = GetClientRequestPrinted( + self, subchild, client_nodeid)
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"])):
+ # absloute address - start address + relative_addr = iecvar["LOC"][3] - int(GetCTVal(child, 3)) + # test if relative address in request specified range + if relative_addr in xrange(int(GetCTVal(child, 2))): 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))
+ "u16 *" + str(iecvar["NAME"]) + " = &client_requests[%d].plcv_buffer[%d];" % (client_requestid, relative_addr)) loc_vars_list.append(str(iecvar["NAME"]))
tcpclient_node_count += 1
- ######################################
if child.PlugType == "ModbusRTUclient":
rtuclient_reqs_count += len(child.IECSortedChildren())
new_node = GetRTUClientNodePrinted(self, child)
client_node_list.append(new_node)
for subchild in child.IECSortedChildren():
- new_req = GetClientRequestPrinted(self, subchild, client_nodeid)
+ new_req = GetClientRequestPrinted( + self, subchild, client_nodeid)
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"])):
+ # absloute address - start address + relative_addr = iecvar["LOC"][3] - int(GetCTVal(child, 3)) + # test if relative address in request specified range + if relative_addr in xrange(int(GetCTVal(child, 2))): 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))
+ "u16 *" + str(iecvar["NAME"]) + " = &client_requests[%d].plcv_buffer[%d];" % (client_requestid, relative_addr)) loc_vars_list.append(str(iecvar["NAME"]))
rtuclient_node_count += 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["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)
@@ -751,20 +767,21 @@
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"])
+ 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
+ # 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 = open(Gen_MB_h_path, 'w') - #same thing as above, but now to .c file
+ # 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 = open(Gen_MB_c_path, 'w') @@ -772,15 +789,16 @@
LDFLAGS.append(" \"-L" + ModbusPath + "\"")
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") + "\"")
+ # 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") + "\"") # Target is ARM with linux and not win on x86 so winsock2 (ws2_32) library is useless !!!
- #if os.name == 'nt': # other possible values: 'posix' 'os2' 'ce' 'java' 'riscos'
- # LDFLAGS.append(" -lws2_32 ") # on windows we need to load winsock library!
+ # if os.name == 'nt': # other possible values: 'posix' 'os2' 'ce' 'java' 'riscos' + # LDFLAGS.append(" -lws2_32 ") # on windows we need to load winsock - return [(Gen_MB_c_path, ' -I"'+ModbusPath+'"')], LDFLAGS, True
+ return [(Gen_MB_c_path, ' -I"' + ModbusPath + '"')], LDFLAGS, True