# HG changeset patch # User Mario de Sousa # Date 1591551272 -3600 # Node ID 54f5b8e5c8d269a95623fbec47267bec8f311249 # Parent 654583c4af83587ae0d36a8654892eb6cedc5ce5 Modbus plugin: fix algorithm detecting Modbus TCP servers using the same IP port on the same network interface diff -r 654583c4af83 -r 54f5b8e5c8d2 modbus/modbus.py --- a/modbus/modbus.py Sun Jun 07 12:28:21 2020 +0100 +++ b/modbus/modbus.py Sun Jun 07 18:34:32 2020 +0100 @@ -409,12 +409,15 @@ 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 + # Return a list with a single tuple conatining the (location, IP address, port number) + # location : location of this node in the configuration tree # port number: IP port used by this Modbus/IP server + # IP address : IP address of the network interface on which the server will be listening + # ("", "*", or "#ANY#" => listening on all interfaces!) def GetIPServerPortNumbers(self): - port = self.GetParamsAttributes()[0]["children"][1]["value"] - return [(self.GetCurrentLocation(), port)] + port = self.ModbusServerNode.getLocal_Port_Number() + addr = self.ModbusServerNode.getLocal_IP_Address() + return [(self.GetCurrentLocation(), addr, port)] def GetConfigName(self): """ Return the node's Configuration_Name """ @@ -691,15 +694,19 @@ # 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 + # + # Also get a list with tuples of (location, IP address, port number) 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_numbers = [(location, IP address, 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) + # IP address : IP address of the network interface on which the server will be listening + # ("", "*", or "#ANY#" => listening on all interfaces!) + # # 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" + # 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 = [] @@ -728,16 +735,19 @@ 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]: - error_message = _("Error: Modbus/IP Servers %{a1}.x and %{a2}.x use the same port number {a3}.\n").format( - a1=_lt_to_str(IPServer_port_numbers[i][0]), - a2=_lt_to_str(IPServer_port_numbers[j][0]), - a3=IPServer_port_numbers[j][1]) + # Note: We only consider duplicate port numbers if using the same network interface! + i = 0 + for loc1, addr1, port1 in IPServer_port_numbers[:-1]: + i = i + 1 + for loc2, addr2, port2 in IPServer_port_numbers[i:]: + if (port1 == port2) and ( + (addr1 == addr2) # on the same network interface + or (addr1 == "") or (addr1 == "*") or (addr1 == "#ANY#") # or one (or both) of the servers + or (addr2 == "") or (addr2 == "*") or (addr2 == "#ANY#") # use all available network interfaces + ): + error_message = _("Error: Modbus plugin nodes %{a1}.x and %{a2}.x use same port number \"{a3}\" " + + "on the same (or overlapping) network interfaces \"{a4}\" and \"{a5}\".\n").format( + a1=_lt_to_str(loc1), a2=_lt_to_str(loc2), a3=port1, a4=addr1, a5=addr2) self.FatalError(error_message) # Determine the current location in Beremiz's project configuration