modbus/modbus.py
changeset 2662 654583c4af83
parent 2654 7575050a80c5
child 2663 54f5b8e5c8d2
equal deleted inserted replaced
2661:9d08e3bba629 2662:654583c4af83
   330     # Return the number of (modbus library) nodes this specific TCP client will need
   330     # Return the number of (modbus library) nodes this specific TCP client will need
   331     #   return type: (tcp nodes, rtu nodes, ascii nodes)
   331     #   return type: (tcp nodes, rtu nodes, ascii nodes)
   332     def GetNodeCount(self):
   332     def GetNodeCount(self):
   333         return (1, 0, 0)
   333         return (1, 0, 0)
   334 
   334 
       
   335     def GetConfigName(self):
       
   336         """ Return the node's Configuration_Name """
       
   337         return self.ModbusTCPclient.getConfiguration_Name()
       
   338 
   335     def CTNGenerate_C(self, buildpath, locations):
   339     def CTNGenerate_C(self, buildpath, locations):
   336         """
   340         """
   337         Generate C code
   341         Generate C code
   338         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   342         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   339         @param locations: List of complete variables locations \
   343         @param locations: List of complete variables locations \
   409     #     location: location of this node in the configuration tree
   413     #     location: location of this node in the configuration tree
   410     #     port number: IP port used by this Modbus/IP server
   414     #     port number: IP port used by this Modbus/IP server
   411     def GetIPServerPortNumbers(self):
   415     def GetIPServerPortNumbers(self):
   412         port = self.GetParamsAttributes()[0]["children"][1]["value"]
   416         port = self.GetParamsAttributes()[0]["children"][1]["value"]
   413         return [(self.GetCurrentLocation(), port)]
   417         return [(self.GetCurrentLocation(), port)]
       
   418 
       
   419     def GetConfigName(self):
       
   420         """ Return the node's Configuration_Name """
       
   421         return self.ModbusServerNode.getConfiguration_Name()
   414 
   422 
   415     def CTNGenerate_C(self, buildpath, locations):
   423     def CTNGenerate_C(self, buildpath, locations):
   416         """
   424         """
   417         Generate C code
   425         Generate C code
   418         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   426         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   497     # Return the number of (modbus library) nodes this specific RTU client will need
   505     # Return the number of (modbus library) nodes this specific RTU client will need
   498     #   return type: (tcp nodes, rtu nodes, ascii nodes)
   506     #   return type: (tcp nodes, rtu nodes, ascii nodes)
   499     def GetNodeCount(self):
   507     def GetNodeCount(self):
   500         return (0, 1, 0)
   508         return (0, 1, 0)
   501 
   509 
       
   510     def GetConfigName(self):
       
   511         """ Return the node's Configuration_Name """
       
   512         return self.ModbusRTUclient.getConfiguration_Name()
       
   513 
   502     def CTNGenerate_C(self, buildpath, locations):
   514     def CTNGenerate_C(self, buildpath, locations):
   503         """
   515         """
   504         Generate C code
   516         Generate C code
   505         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   517         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   506         @param locations: List of complete variables locations \
   518         @param locations: List of complete variables locations \
   583     # Return the number of (modbus library) nodes this specific RTU slave will need
   595     # Return the number of (modbus library) nodes this specific RTU slave will need
   584     #   return type: (tcp nodes, rtu nodes, ascii nodes)
   596     #   return type: (tcp nodes, rtu nodes, ascii nodes)
   585     def GetNodeCount(self):
   597     def GetNodeCount(self):
   586         return (0, 1, 0)
   598         return (0, 1, 0)
   587 
   599 
       
   600     def GetConfigName(self):
       
   601         """ Return the node's Configuration_Name """
       
   602         return self.ModbusRTUslave.getConfiguration_Name()
       
   603 
   588     def CTNGenerate_C(self, buildpath, locations):
   604     def CTNGenerate_C(self, buildpath, locations):
   589         """
   605         """
   590         Generate C code
   606         Generate C code
   591         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   607         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   592         @param locations: List of complete variables locations \
   608         @param locations: List of complete variables locations \
   644             # ask each child how many nodes it needs, and add them all up.
   660             # ask each child how many nodes it needs, and add them all up.
   645             total_node_count = tuple(
   661             total_node_count = tuple(
   646                 x1 + x2 for x1, x2 in zip(total_node_count, child.GetNodeCount()))
   662                 x1 + x2 for x1, x2 in zip(total_node_count, child.GetNodeCount()))
   647         return total_node_count
   663         return total_node_count
   648 
   664 
   649     # Return a list with tuples of the (location, port numbers) used by all
   665     # Return a list with tuples of the (location, port numbers) used by all the Modbus/IP servers
   650     # the Modbus/IP servers
       
   651     def GetIPServerPortNumbers(self):
   666     def GetIPServerPortNumbers(self):
   652         IPServer_port_numbers = []
   667         IPServer_port_numbers = []
   653         for child in self.IECSortedChildren():
   668         for child in self.IECSortedChildren():
   654             if child.CTNType == "ModbusTCPserver":
   669             if child.CTNType == "ModbusTCPserver":
   655                 IPServer_port_numbers.extend(child.GetIPServerPortNumbers())
   670                 IPServer_port_numbers.extend(child.GetIPServerPortNumbers())
   656         return IPServer_port_numbers
   671         return IPServer_port_numbers
       
   672 
       
   673     # Return a list with tuples of the (location, configuration_name) used by all the Modbus nodes (tcp/rtu, clients/servers)
       
   674     def GetConfigNames(self):
       
   675         Node_Configuration_Names = []
       
   676         for child in self.IECSortedChildren():
       
   677             Node_Configuration_Names.extend([(child.GetCurrentLocation(), child.GetConfigName())])
       
   678         return Node_Configuration_Names
   657 
   679 
   658     def CTNGenerate_C(self, buildpath, locations):
   680     def CTNGenerate_C(self, buildpath, locations):
   659         # print "#############"
   681         # print "#############"
   660         # print self.__class__
   682         # print self.__class__
   661         # print type(self)
   683         # print type(self)
   671         #   total_node_count: (tcp nodes, rtu nodes, ascii nodes)
   693         #   total_node_count: (tcp nodes, rtu nodes, ascii nodes)
   672         # Also get a list with tuples of (location, IP port numbers) used by all the Modbus/IP server nodes
   694         # Also get a list with tuples of (location, IP port numbers) used by all the Modbus/IP server nodes
   673         #   This list is later used to search for duplicates in port numbers!
   695         #   This list is later used to search for duplicates in port numbers!
   674         #   IPServer_port_numbers = [(location ,IPserver_port_number), ...]
   696         #   IPServer_port_numbers = [(location ,IPserver_port_number), ...]
   675         #       location: tuple similar to (0, 3, 1) representing the location in the configuration tree "0.3.1.x"
   697         #       location: tuple similar to (0, 3, 1) representing the location in the configuration tree "0.3.1.x"
   676         # IPserver_port_number: a number (i.e. port number used by the
   698         #       IPserver_port_number: a number (i.e. port number used by the Modbus/IP server)
   677         # Modbus/IP server)
   699         # Also get a list with tuples of (location, Configuration_Name) used by all the Modbus nodes
       
   700         #   This list is later used to search for duplicates in Configuration Names!
       
   701         #   Node_Configuration_Names = [(location, Configuration_Name), ...]
       
   702         #       location: tuple similar to (0, 3, 1) representing the location in the configuration tree "0.3.1.x"
       
   703         #       Configuration_Name: the "Configuration_Name" string
   678         total_node_count = (0, 0, 0)
   704         total_node_count = (0, 0, 0)
   679         IPServer_port_numbers = []
   705         IPServer_port_numbers    = []
       
   706         Node_Configuration_Names = []
   680         for CTNInstance in self.GetCTRoot().IterChildren():
   707         for CTNInstance in self.GetCTRoot().IterChildren():
   681             if CTNInstance.CTNType == "modbus":
   708             if CTNInstance.CTNType == "modbus":
   682                 # ask each modbus plugin instance how many nodes it needs, and
   709                 # ask each modbus plugin instance how many nodes it needs, and add them all up.
   683                 # add them all up.
   710                 total_node_count = tuple(x1 + x2 for x1, x2 in zip(total_node_count, CTNInstance.GetNodeCount()))
   684                 total_node_count = tuple(x1 + x2 for x1, x2 in zip(
   711                 IPServer_port_numbers.   extend(CTNInstance.GetIPServerPortNumbers())
   685                     total_node_count, CTNInstance.GetNodeCount()))
   712                 Node_Configuration_Names.extend(CTNInstance.GetConfigNames        ())
   686                 IPServer_port_numbers.extend(
   713 
   687                     CTNInstance.GetIPServerPortNumbers())
   714         # Search for use of duplicate Configuration_Names by Modbus nodes
       
   715         # Configuration Names are used by the web server running on the PLC
       
   716         # (more precisely, run by Beremiz_service.py) to identify and allow 
       
   717         # changing the Modbus parameters after the program has been downloaded 
       
   718         # to the PLC (but before it is started)
       
   719         # With clashes in the configuration names, the Modbus nodes will not be
       
   720         # distinguasheble on the web interface!
       
   721         for i in range(0, len(Node_Configuration_Names) - 1):
       
   722             for j in range(i + 1, len(Node_Configuration_Names)):
       
   723                 if Node_Configuration_Names[i][1] == Node_Configuration_Names[j][1]:
       
   724                     error_message = _("Error: Modbus plugin nodes %{a1}.x and %{a2}.x use the same Configuration_Name \"{a3}\".\n").format(
       
   725                                         a1=_lt_to_str(Node_Configuration_Names[i][0]),
       
   726                                         a2=_lt_to_str(Node_Configuration_Names[j][0]),
       
   727                                         a3=Node_Configuration_Names[j][1])
       
   728                     self.FatalError(error_message)
   688 
   729 
   689         # Search for use of duplicate port numbers by Modbus/IP servers
   730         # Search for use of duplicate port numbers by Modbus/IP servers
   690         # print IPServer_port_numbers
   731         # print IPServer_port_numbers
   691         # ..but first define a lambda function to convert a tuple with the config tree location to a nice looking string
   732         # ..but first define a lambda function to convert a tuple with the config tree location to a nice looking string
   692         #   for e.g., convert the tuple (0, 3, 4) to "0.3.4"
   733         #   for e.g., convert the tuple (0, 3, 4) to "0.3.4"
   693 
       
   694         for i in range(0, len(IPServer_port_numbers) - 1):
   734         for i in range(0, len(IPServer_port_numbers) - 1):
   695             for j in range(i + 1, len(IPServer_port_numbers)):
   735             for j in range(i + 1, len(IPServer_port_numbers)):
   696                 if IPServer_port_numbers[i][1] == IPServer_port_numbers[j][1]:
   736                 if IPServer_port_numbers[i][1] == IPServer_port_numbers[j][1]:
   697                     error_message = _("Error: Modbus/IP Servers %{a1}.x and %{a2}.x use the same port number {a3}.\n").format(
   737                     error_message = _("Error: Modbus/IP Servers %{a1}.x and %{a2}.x use the same port number {a3}.\n").format(
   698                                         a1=_lt_to_str(IPServer_port_numbers[i][0]),
   738                                         a1=_lt_to_str(IPServer_port_numbers[i][0]),
   699                                         a2=_lt_to_str(IPServer_port_numbers[j][0]),
   739                                         a2=_lt_to_str(IPServer_port_numbers[j][0]),
   700                                         a3=IPServer_port_numbers[j][1])
   740                                         a3=IPServer_port_numbers[j][1])
   701                     self.FatalError(error_message)
   741                     self.FatalError(error_message)
   702                     #self.GetCTRoot().logger.write_warning(error_message)
       
   703                     #raise Exception
       
   704 
   742 
   705         # Determine the current location in Beremiz's project configuration
   743         # Determine the current location in Beremiz's project configuration
   706         # tree
   744         # tree
   707         current_location = self.GetCurrentLocation()
   745         current_location = self.GetCurrentLocation()
   708 
   746