modbus/modbus.py
changeset 2721 367eb26972b1
parent 2717 b3b6991f1cb6
child 2722 5d72a52b8f9c
equal deleted inserted replaced
2717:b3b6991f1cb6 2721:367eb26972b1
   440 
   440 
   441     def GetConfigName(self):
   441     def GetConfigName(self):
   442         """ Return the node's Configuration_Name """
   442         """ Return the node's Configuration_Name """
   443         return self.ModbusServerNode.getConfiguration_Name()
   443         return self.ModbusServerNode.getConfiguration_Name()
   444 
   444 
       
   445     def GetVariableLocationTree(self):
       
   446         current_location = self.GetCurrentLocation()
       
   447         name             = self.BaseParams.getName()
       
   448         # start off with flags that count the number of Modbus requests/transactions
       
   449         # handled by this Modbus server/slave.
       
   450         # These flags are mapped onto located variables and therefore available to the user programs
       
   451         # May be used to detect communication errors.
       
   452         # execute the Modbus request.
       
   453         # NOTE: If the Modbus slave has a 'current_location' of
       
   454         #          %QX1.2
       
   455         #       then the "Modbus Read Request Counter" will be
       
   456         #          %MD1.2.0
       
   457         #       then the "Modbus Write Request Counter" will be
       
   458         #          %MD1.2.1
       
   459         #
       
   460         # Note that any MemoryArea contained under this server/slave
       
   461         # will ocupy the locations of type
       
   462         #          %MX or %MW
       
   463         # which will never clash with the %MD used here.
       
   464         # Additionaly, any MemoryArea contained under this server/slave
       
   465         # will ocupy locations with
       
   466         #           %M1.2.a.b (with a and b being numbers in range 0, 1, ...)
       
   467         # and therefore never ocupy the locations
       
   468         #           %M1.2.0
       
   469         #           %M1.2.1
       
   470         # used by the following flags/counters.
       
   471         entries = []
       
   472         entries.append({
       
   473             "name": "Modbus Read Request Counter",
       
   474             "type": LOCATION_VAR_MEMORY,
       
   475             "size": 32,           # UDINT flag
       
   476             "IEC_type": "UDINT",  # UDINT flag
       
   477             "var_name": "var_name",
       
   478             "location": "D" + ".".join([str(i) for i in current_location]) + ".0",
       
   479             "description": "Modbus read request counter",
       
   480             "children": []})        
       
   481         entries.append({
       
   482             "name": "Modbus Write Request Counter",
       
   483             "type": LOCATION_VAR_MEMORY,
       
   484             "size": 32,           # UDINT flag
       
   485             "IEC_type": "UDINT",  # UDINT flag
       
   486             "var_name": "var_name",
       
   487             "location": "D" + ".".join([str(i) for i in current_location]) + ".1",
       
   488             "description": "Modbus write request counter",
       
   489             "children": []})        
       
   490         # recursively call all the Memory Areas under this Modbus server/save
       
   491         # i.e., all the children objects which will be of class _MemoryAreaPlug
       
   492         for child in self.IECSortedChildren():
       
   493             entries.append(child.GetVariableLocationTree())
       
   494 
       
   495         return {"name": name,
       
   496                 "type": LOCATION_CONFNODE,
       
   497                 "location": ".".join([str(i) for i in current_location]) + ".x",
       
   498                 "children": entries}
       
   499 
       
   500 
   445     def CTNGenerate_C(self, buildpath, locations):
   501     def CTNGenerate_C(self, buildpath, locations):
   446         """
   502         """
   447         Generate C code
   503         Generate C code
   448         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   504         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   449         @param locations: List of complete variables locations \
   505         @param locations: List of complete variables locations \
   621 
   677 
   622     def GetConfigName(self):
   678     def GetConfigName(self):
   623         """ Return the node's Configuration_Name """
   679         """ Return the node's Configuration_Name """
   624         return self.ModbusRTUslave.getConfiguration_Name()
   680         return self.ModbusRTUslave.getConfiguration_Name()
   625 
   681 
       
   682     def GetVariableLocationTree(self):
       
   683         current_location = self.GetCurrentLocation()
       
   684         name             = self.BaseParams.getName()
       
   685         # start off with flags that count the number of Modbus requests/transactions
       
   686         # handled by this Modbus server/slave.
       
   687         # These flags are mapped onto located variables and therefore available to the user programs
       
   688         # May be used to detect communication errors.
       
   689         # execute the Modbus request.
       
   690         # NOTE: If the Modbus slave has a 'current_location' of
       
   691         #          %QX1.2
       
   692         #       then the "Modbus Read Request Counter" will be
       
   693         #          %MD1.2.0
       
   694         #       then the "Modbus Write Request Counter" will be
       
   695         #          %MD1.2.1
       
   696         #
       
   697         # Note that any MemoryArea contained under this server/slave
       
   698         # will ocupy the locations of type
       
   699         #          %MX or %MW
       
   700         # which will never clash with the %MD used here.
       
   701         # Additionaly, any MemoryArea contained under this server/slave
       
   702         # will ocupy locations with
       
   703         #           %M1.2.a.b (with a and b being numbers in range 0, 1, ...)
       
   704         # and therefore never ocupy the locations
       
   705         #           %M1.2.0
       
   706         #           %M1.2.1
       
   707         # used by the following flags/counters.
       
   708         entries = []
       
   709         entries.append({
       
   710             "name": "Modbus Read Request Counter",
       
   711             "type": LOCATION_VAR_MEMORY,
       
   712             "size": 32,           # UDINT flag
       
   713             "IEC_type": "UDINT",  # UDINT flag
       
   714             "var_name": "var_name",
       
   715             "location": "D" + ".".join([str(i) for i in current_location]) + ".0",
       
   716             "description": "Modbus read request counter",
       
   717             "children": []})        
       
   718         entries.append({
       
   719             "name": "Modbus Write Request Counter",
       
   720             "type": LOCATION_VAR_MEMORY,
       
   721             "size": 32,           # UDINT flag
       
   722             "IEC_type": "UDINT",  # UDINT flag
       
   723             "var_name": "var_name",
       
   724             "location": "D" + ".".join([str(i) for i in current_location]) + ".1",
       
   725             "description": "Modbus write request counter",
       
   726             "children": []})        
       
   727         # recursively call all the Memory Areas under this Modbus server/save
       
   728         # i.e., all the children objects which will be of class _MemoryAreaPlug
       
   729         for child in self.IECSortedChildren():
       
   730             entries.append(child.GetVariableLocationTree())
       
   731 
       
   732         return {"name": name,
       
   733                 "type": LOCATION_CONFNODE,
       
   734                 "location": ".".join([str(i) for i in current_location]) + ".x",
       
   735                 "children": entries}
       
   736 
       
   737 
   626     def CTNGenerate_C(self, buildpath, locations):
   738     def CTNGenerate_C(self, buildpath, locations):
   627         """
   739         """
   628         Generate C code
   740         Generate C code
   629         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   741         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   630         @param locations: List of complete variables locations \
   742         @param locations: List of complete variables locations \
   809             if child.PlugType == "ModbusTCPserver":
   921             if child.PlugType == "ModbusTCPserver":
   810                 tcpserver_node_count += 1
   922                 tcpserver_node_count += 1
   811                 new_node = GetTCPServerNodePrinted(self, child)
   923                 new_node = GetTCPServerNodePrinted(self, child)
   812                 if new_node is None:
   924                 if new_node is None:
   813                     return [], "", False
   925                     return [], "", False
   814                 server_node_list.append(new_node)
   926                 server_node_list.append(new_node)                
       
   927                 #        We currently add 2 flags/counters to each Modbus server/slave
   815                 #
   928                 #
       
   929                 # TODO: fix comment
       
   930                 #        We add the "Execution Control Flag" to each client request (one flag per request)
       
   931                 #        to allow the user program to control when to execute the request (if not executed periodically)
       
   932                 #        While all Modbus registers/coils are mapped onto a location
       
   933                 #        with 4 numbers (e.g. %QX0.1.2.55), this control flag is mapped
       
   934                 #        onto a location with 4 numbers (e.g. %QX0.1.2.0.0), where the last
       
   935                 #        two numbers are always '0.0', and the first two identify the request.
       
   936                 #        In the following if, we check for this condition by checking
       
   937                 #        if there are at least 4 or more number in the location's address.
       
   938                 for iecvar in child.GetLocations():
       
   939                     #print "child" + repr(iecvar)
       
   940                     if (len(iecvar["LOC"]) == 3) and (str(iecvar["NAME"]) not in loc_vars_list):
       
   941                         # Add if it is a "Modbus Read Request Counter" (mapped onto %MDa.b.0), so last number is a '0'
       
   942                         if iecvar["LOC"][2] == 0:
       
   943                             loc_vars.append("u32 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.flag_read_req_counter;" % (server_id))
       
   944                             loc_vars_list.append(str(iecvar["NAME"]))
       
   945                         # Add if it is a "Modbus Write Request Counter" (mapped onto %MDa.b.1), so last number is a '1'
       
   946                         if iecvar["LOC"][2] == 1:
       
   947                             loc_vars.append("u32 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.flag_write_req_counter;" % (server_id))
       
   948                             loc_vars_list.append(str(iecvar["NAME"]))
       
   949                 
   816                 for subchild in child.IECSortedChildren():
   950                 for subchild in child.IECSortedChildren():
   817                     new_memarea = GetTCPServerMemAreaPrinted(
   951                     new_memarea = GetTCPServerMemAreaPrinted(self, subchild, nodeid)
   818                         self, subchild, nodeid)
       
   819                     if new_memarea is None:
   952                     if new_memarea is None:
   820                         return [], "", False
   953                         return [], "", False
   821                     server_memarea_list.append(new_memarea)
   954                     server_memarea_list.append(new_memarea)
   822                     function = subchild.GetParamsAttributes()[
   955                     function = subchild.GetParamsAttributes()[0]["children"][0]["value"]
   823                         0]["children"][0]["value"]
       
   824                     # 'ro_bits', 'rw_bits', 'ro_words' or 'rw_words'
   956                     # 'ro_bits', 'rw_bits', 'ro_words' or 'rw_words'
   825                     memarea = modbus_memtype_dict[function][1]
   957                     memarea = modbus_memtype_dict[function][1]
   826                     for iecvar in subchild.GetLocations():
   958                     for iecvar in subchild.GetLocations():
   827                         # print repr(iecvar)
   959                         if len(iecvar["LOC"]) == 4:
   828                         absloute_address = iecvar["LOC"][3]
   960                             #print "subchild" + repr(iecvar)
   829                         start_address = int(GetCTVal(subchild, 2))
   961                             absloute_address = iecvar["LOC"][3]
   830                         relative_addr = absloute_address - start_address
   962                             start_address = int(GetCTVal(subchild, 2))
   831                         # test if relative address in request specified range
   963                             relative_addr = absloute_address - start_address
   832                         if relative_addr in xrange(int(GetCTVal(subchild, 1))):
   964                             # test if relative address in request specified range
   833                             if str(iecvar["NAME"]) not in loc_vars_list:
   965                             if relative_addr in xrange(int(GetCTVal(subchild, 1))):
   834                                 loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.%s[%d];" % (
   966                                 if str(iecvar["NAME"]) not in loc_vars_list:
   835                                     server_id, memarea, absloute_address))
   967                                     loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.%s[%d];" % (
   836                                 loc_vars_list.append(str(iecvar["NAME"]))
   968                                         server_id, memarea, absloute_address))
       
   969                                     loc_vars_list.append(str(iecvar["NAME"]))
   837                 server_id += 1
   970                 server_id += 1
   838             #
   971             #
   839             if child.PlugType == "ModbusRTUslave":
   972             if child.PlugType == "ModbusRTUslave":
   840                 rtuserver_node_count += 1
   973                 rtuserver_node_count += 1
   841                 new_node = GetRTUSlaveNodePrinted(self, child)
   974                 new_node = GetRTUSlaveNodePrinted(self, child)
   847                     new_memarea = GetTCPServerMemAreaPrinted(
   980                     new_memarea = GetTCPServerMemAreaPrinted(
   848                         self, subchild, nodeid)
   981                         self, subchild, nodeid)
   849                     if new_memarea is None:
   982                     if new_memarea is None:
   850                         return [], "", False
   983                         return [], "", False
   851                     server_memarea_list.append(new_memarea)
   984                     server_memarea_list.append(new_memarea)
   852                     function = subchild.GetParamsAttributes()[
   985                     function = subchild.GetParamsAttributes()[0]["children"][0]["value"]
   853                         0]["children"][0]["value"]
       
   854                     # 'ro_bits', 'rw_bits', 'ro_words' or 'rw_words'
   986                     # 'ro_bits', 'rw_bits', 'ro_words' or 'rw_words'
   855                     memarea = modbus_memtype_dict[function][1]
   987                     memarea = modbus_memtype_dict[function][1]
   856                     for iecvar in subchild.GetLocations():
   988                     for iecvar in subchild.GetLocations():
   857                         # print repr(iecvar)
   989                         if len(iecvar["LOC"]) == 4:
   858                         absloute_address = iecvar["LOC"][3]
   990                             # print repr(iecvar)
   859                         start_address = int(GetCTVal(subchild, 2))
   991                             absloute_address = iecvar["LOC"][3]
   860                         relative_addr = absloute_address - start_address
   992                             start_address = int(GetCTVal(subchild, 2))
   861                         # test if relative address in request specified range
   993                             relative_addr = absloute_address - start_address
   862                         if relative_addr in xrange(int(GetCTVal(subchild, 1))):
   994                             # test if relative address in request specified range
   863                             if str(iecvar["NAME"]) not in loc_vars_list:
   995                             if relative_addr in xrange(int(GetCTVal(subchild, 1))):
   864                                 loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.%s[%d];" % (
   996                                 if str(iecvar["NAME"]) not in loc_vars_list:
   865                                     server_id, memarea, absloute_address))
   997                                     loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.%s[%d];" % (
   866                                 loc_vars_list.append(str(iecvar["NAME"]))
   998                                         server_id, memarea, absloute_address))
       
   999                                     loc_vars_list.append(str(iecvar["NAME"]))
   867                 server_id += 1
  1000                 server_id += 1
   868             #
  1001             #
   869             if child.PlugType == "ModbusTCPclient":
  1002             if child.PlugType == "ModbusTCPclient":
   870                 tcpclient_reqs_count += len(child.IECSortedChildren())
  1003                 tcpclient_reqs_count += len(child.IECSortedChildren())
   871                 new_node = GetTCPClientNodePrinted(self, child)
  1004                 new_node = GetTCPClientNodePrinted(self, child)