# HG changeset patch # User Mario de Sousa # Date 1591529301 -3600 # Node ID 654583c4af83587ae0d36a8654892eb6cedc5ce5 # Parent 9d08e3bba629c43f66ace9334a24dbdcf8f0bbf1 Modbus plugin: check for duplicate "Configuration_Name" diff -r 9d08e3bba629 -r 654583c4af83 modbus/modbus.py --- a/modbus/modbus.py Sat Jun 06 08:51:32 2020 +0100 +++ b/modbus/modbus.py Sun Jun 07 12:28:21 2020 +0100 @@ -332,6 +332,10 @@ def GetNodeCount(self): return (1, 0, 0) + def GetConfigName(self): + """ Return the node's Configuration_Name """ + return self.ModbusTCPclient.getConfiguration_Name() + def CTNGenerate_C(self, buildpath, locations): """ Generate C code @@ -412,6 +416,10 @@ port = self.GetParamsAttributes()[0]["children"][1]["value"] return [(self.GetCurrentLocation(), port)] + def GetConfigName(self): + """ Return the node's Configuration_Name """ + return self.ModbusServerNode.getConfiguration_Name() + def CTNGenerate_C(self, buildpath, locations): """ Generate C code @@ -499,6 +507,10 @@ def GetNodeCount(self): return (0, 1, 0) + def GetConfigName(self): + """ Return the node's Configuration_Name """ + return self.ModbusRTUclient.getConfiguration_Name() + def CTNGenerate_C(self, buildpath, locations): """ Generate C code @@ -585,6 +597,10 @@ def GetNodeCount(self): return (0, 1, 0) + def GetConfigName(self): + """ Return the node's Configuration_Name """ + return self.ModbusRTUslave.getConfiguration_Name() + def CTNGenerate_C(self, buildpath, locations): """ Generate C code @@ -646,8 +662,7 @@ 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 + # 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(): @@ -655,6 +670,13 @@ IPServer_port_numbers.extend(child.GetIPServerPortNumbers()) return IPServer_port_numbers + # Return a list with tuples of the (location, configuration_name) used by all the Modbus nodes (tcp/rtu, clients/servers) + def GetConfigNames(self): + Node_Configuration_Names = [] + for child in self.IECSortedChildren(): + Node_Configuration_Names.extend([(child.GetCurrentLocation(), child.GetConfigName())]) + return Node_Configuration_Names + def CTNGenerate_C(self, buildpath, locations): # print "#############" # print self.__class__ @@ -673,24 +695,42 @@ # 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 Modbus/IP server) + # Also get a list with tuples of (location, Configuration_Name) used by all the Modbus nodes + # This list is later used to search for duplicates in Configuration Names! + # Node_Configuration_Names = [(location, Configuration_Name), ...] + # location: tuple similar to (0, 3, 1) representing the location in the configuration tree "0.3.1.x" + # Configuration_Name: the "Configuration_Name" string total_node_count = (0, 0, 0) - IPServer_port_numbers = [] + IPServer_port_numbers = [] + Node_Configuration_Names = [] 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 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()) + Node_Configuration_Names.extend(CTNInstance.GetConfigNames ()) + + # Search for use of duplicate Configuration_Names by Modbus nodes + # Configuration Names are used by the web server running on the PLC + # (more precisely, run by Beremiz_service.py) to identify and allow + # changing the Modbus parameters after the program has been downloaded + # to the PLC (but before it is started) + # With clashes in the configuration names, the Modbus nodes will not be + # distinguasheble on the web interface! + for i in range(0, len(Node_Configuration_Names) - 1): + for j in range(i + 1, len(Node_Configuration_Names)): + if Node_Configuration_Names[i][1] == Node_Configuration_Names[j][1]: + error_message = _("Error: Modbus plugin nodes %{a1}.x and %{a2}.x use the same Configuration_Name \"{a3}\".\n").format( + a1=_lt_to_str(Node_Configuration_Names[i][0]), + a2=_lt_to_str(Node_Configuration_Names[j][0]), + a3=Node_Configuration_Names[j][1]) + self.FatalError(error_message) # 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" - 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]: @@ -699,8 +739,6 @@ a2=_lt_to_str(IPServer_port_numbers[j][0]), a3=IPServer_port_numbers[j][1]) self.FatalError(error_message) - #self.GetCTRoot().logger.write_warning(error_message) - #raise Exception # Determine the current location in Beremiz's project configuration # tree