Modbus plugin: check for duplicate "Configuration_Name"
authorMario de Sousa <msousa@fe.up.pt>
Sun, 07 Jun 2020 12:28:21 +0100
changeset 2662 654583c4af83
parent 2661 9d08e3bba629
child 2663 54f5b8e5c8d2
Modbus plugin: check for duplicate "Configuration_Name"
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