modbus/modbus.py
changeset 2723 cde2e410b874
parent 2718 76e8ec46828a
parent 2722 5d72a52b8f9c
child 2724 3f3f9dce9140
equal deleted inserted replaced
2718:76e8ec46828a 2723:cde2e410b874
   445 
   445 
   446     def GetConfigName(self):
   446     def GetConfigName(self):
   447         """ Return the node's Configuration_Name """
   447         """ Return the node's Configuration_Name """
   448         return self.ModbusServerNode.getConfiguration_Name()
   448         return self.ModbusServerNode.getConfiguration_Name()
   449 
   449 
       
   450     def GetVariableLocationTree(self):
       
   451         current_location = self.GetCurrentLocation()
       
   452         name             = self.BaseParams.getName()
       
   453         # start off with flags that count the number of Modbus requests/transactions
       
   454         # handled by this Modbus server/slave.
       
   455         # These flags are mapped onto located variables and therefore available to the user programs
       
   456         # May be used to detect communication errors.
       
   457         # execute the Modbus request.
       
   458         # NOTE: If the Modbus slave has a 'current_location' of
       
   459         #          %QX1.2
       
   460         #       then the "Modbus Read Request Counter"  will be %MD1.2.0
       
   461         #       then the "Modbus Write Request Counter" will be %MD1.2.1
       
   462         #       then the "Modbus Read Request Flag"     will be %MD1.2.2
       
   463         #       then the "Modbus Write Request Flag"    will be %MD1.2.3
       
   464         #
       
   465         # Note that any MemoryArea contained under this server/slave
       
   466         # will ocupy the locations of type
       
   467         #          %MX or %MW
       
   468         # which will never clash with the %MD used here.
       
   469         # Additionaly, any MemoryArea contained under this server/slave
       
   470         # will ocupy locations with
       
   471         #           %M1.2.a.b (with a and b being numbers in range 0, 1, ...)
       
   472         # and therefore never ocupy the locations
       
   473         #           %M1.2.0
       
   474         #           %M1.2.1
       
   475         #           %M1.2.2
       
   476         #           %M1.2.3
       
   477         # used by the following flags/counters.
       
   478         entries = []
       
   479         entries.append({
       
   480             "name": "Modbus Read Request Counter",
       
   481             "type": LOCATION_VAR_MEMORY,
       
   482             "size": 32,           # UDINT flag
       
   483             "IEC_type": "UDINT",  # UDINT flag
       
   484             "var_name": "var_name",
       
   485             "location": "D" + ".".join([str(i) for i in current_location]) + ".0",
       
   486             "description": "Modbus read request counter",
       
   487             "children": []})        
       
   488         entries.append({
       
   489             "name": "Modbus Write Request Counter",
       
   490             "type": LOCATION_VAR_MEMORY,
       
   491             "size": 32,           # UDINT flag
       
   492             "IEC_type": "UDINT",  # UDINT flag
       
   493             "var_name": "var_name",
       
   494             "location": "D" + ".".join([str(i) for i in current_location]) + ".1",
       
   495             "description": "Modbus write request counter",
       
   496             "children": []})        
       
   497         entries.append({
       
   498             "name": "Modbus Read Request Flag",
       
   499             "type": LOCATION_VAR_MEMORY,
       
   500             "size": 1,            # BOOL flag
       
   501             "IEC_type": "BOOL",   # BOOL flag
       
   502             "var_name": "var_name",
       
   503             "location": "X" + ".".join([str(i) for i in current_location]) + ".2",
       
   504             "description": "Modbus read request flag",
       
   505             "children": []})        
       
   506         entries.append({
       
   507             "name": "Modbus write Request Flag",
       
   508             "type": LOCATION_VAR_MEMORY,
       
   509             "size": 1,            # BOOL flag
       
   510             "IEC_type": "BOOL",   # BOOL flag
       
   511             "var_name": "var_name",
       
   512             "location": "X" + ".".join([str(i) for i in current_location]) + ".3",
       
   513             "description": "Modbus write request flag",
       
   514             "children": []})        
       
   515         # recursively call all the Memory Areas under this Modbus server/save
       
   516         # i.e., all the children objects which will be of class _MemoryAreaPlug
       
   517         for child in self.IECSortedChildren():
       
   518             entries.append(child.GetVariableLocationTree())
       
   519 
       
   520         return {"name": name,
       
   521                 "type": LOCATION_CONFNODE,
       
   522                 "location": ".".join([str(i) for i in current_location]) + ".x",
       
   523                 "children": entries}
       
   524 
       
   525 
   450     def CTNGenerate_C(self, buildpath, locations):
   526     def CTNGenerate_C(self, buildpath, locations):
   451         """
   527         """
   452         Generate C code
   528         Generate C code
   453         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   529         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   454         @param locations: List of complete variables locations \
   530         @param locations: List of complete variables locations \
   629 
   705 
   630     def GetConfigName(self):
   706     def GetConfigName(self):
   631         """ Return the node's Configuration_Name """
   707         """ Return the node's Configuration_Name """
   632         return self.ModbusRTUslave.getConfiguration_Name()
   708         return self.ModbusRTUslave.getConfiguration_Name()
   633 
   709 
       
   710     def GetVariableLocationTree(self):
       
   711         current_location = self.GetCurrentLocation()
       
   712         name             = self.BaseParams.getName()
       
   713         # start off with flags that count the number of Modbus requests/transactions
       
   714         # handled by this Modbus server/slave.
       
   715         # These flags are mapped onto located variables and therefore available to the user programs
       
   716         # May be used to detect communication errors.
       
   717         # execute the Modbus request.
       
   718         # NOTE: If the Modbus slave has a 'current_location' of
       
   719         #          %QX1.2
       
   720         #       then the "Modbus Read Request Counter"  will be %MD1.2.0
       
   721         #       then the "Modbus Write Request Counter" will be %MD1.2.1
       
   722         #       then the "Modbus Read Request Flag"     will be %MD1.2.2
       
   723         #       then the "Modbus Write Request Flag"    will be %MD1.2.3
       
   724         #
       
   725         # Note that any MemoryArea contained under this server/slave
       
   726         # will ocupy the locations of type
       
   727         #          %MX or %MW
       
   728         # which will never clash with the %MD used here.
       
   729         # Additionaly, any MemoryArea contained under this server/slave
       
   730         # will ocupy locations with
       
   731         #           %M1.2.a.b (with a and b being numbers in range 0, 1, ...)
       
   732         # and therefore never ocupy the locations
       
   733         #           %M1.2.0
       
   734         #           %M1.2.1
       
   735         #           %M1.2.2
       
   736         #           %M1.2.3
       
   737         # used by the following flags/counters.
       
   738         entries = []
       
   739         entries.append({
       
   740             "name": "Modbus Read Request Counter",
       
   741             "type": LOCATION_VAR_MEMORY,
       
   742             "size": 32,           # UDINT flag
       
   743             "IEC_type": "UDINT",  # UDINT flag
       
   744             "var_name": "var_name",
       
   745             "location": "D" + ".".join([str(i) for i in current_location]) + ".0",
       
   746             "description": "Modbus read request counter",
       
   747             "children": []})        
       
   748         entries.append({
       
   749             "name": "Modbus Write Request Counter",
       
   750             "type": LOCATION_VAR_MEMORY,
       
   751             "size": 32,           # UDINT flag
       
   752             "IEC_type": "UDINT",  # UDINT flag
       
   753             "var_name": "var_name",
       
   754             "location": "D" + ".".join([str(i) for i in current_location]) + ".1",
       
   755             "description": "Modbus write request counter",
       
   756             "children": []})        
       
   757         entries.append({
       
   758             "name": "Modbus Read Request Flag",
       
   759             "type": LOCATION_VAR_MEMORY,
       
   760             "size": 1,            # BOOL flag
       
   761             "IEC_type": "BOOL",   # BOOL flag
       
   762             "var_name": "var_name",
       
   763             "location": "X" + ".".join([str(i) for i in current_location]) + ".2",
       
   764             "description": "Modbus read request flag",
       
   765             "children": []})        
       
   766         entries.append({
       
   767             "name": "Modbus write Request Flag",
       
   768             "type": LOCATION_VAR_MEMORY,
       
   769             "size": 1,            # BOOL flag
       
   770             "IEC_type": "BOOL",   # BOOL flag
       
   771             "var_name": "var_name",
       
   772             "location": "X" + ".".join([str(i) for i in current_location]) + ".3",
       
   773             "description": "Modbus write request flag",
       
   774             "children": []})        
       
   775         # recursively call all the Memory Areas under this Modbus server/save
       
   776         # i.e., all the children objects which will be of class _MemoryAreaPlug
       
   777         for child in self.IECSortedChildren():
       
   778             entries.append(child.GetVariableLocationTree())
       
   779 
       
   780         return {"name": name,
       
   781                 "type": LOCATION_CONFNODE,
       
   782                 "location": ".".join([str(i) for i in current_location]) + ".x",
       
   783                 "children": entries}
       
   784 
       
   785 
   634     def CTNGenerate_C(self, buildpath, locations):
   786     def CTNGenerate_C(self, buildpath, locations):
   635         """
   787         """
   636         Generate C code
   788         Generate C code
   637         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   789         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   638         @param locations: List of complete variables locations \
   790         @param locations: List of complete variables locations \
   817             if child.PlugType == "ModbusTCPserver":
   969             if child.PlugType == "ModbusTCPserver":
   818                 tcpserver_node_count += 1
   970                 tcpserver_node_count += 1
   819                 new_node = GetTCPServerNodePrinted(self, child)
   971                 new_node = GetTCPServerNodePrinted(self, child)
   820                 if new_node is None:
   972                 if new_node is None:
   821                     return [], "", False
   973                     return [], "", False
   822                 server_node_list.append(new_node)
   974                 server_node_list.append(new_node)                
       
   975                 #        We currently add 4 flags/counters to each Modbus server/slave
   823                 #
   976                 #
       
   977                 #        We add the Modbus read/write counter/flag to each Modbus slave/server
       
   978                 #        to allow the user program to determine if the slave is being actively
       
   979                 #        read from or written by by a remote Modbus client.
       
   980                 for iecvar in child.GetLocations():
       
   981                     #print "child" + repr(iecvar)
       
   982                     if (len(iecvar["LOC"]) == 3) and (str(iecvar["NAME"]) not in loc_vars_list):
       
   983                         # Add if it is a "Modbus Read Request Counter" (mapped onto %MDa.b.0), so last number is a '0'
       
   984                         if iecvar["LOC"][2] == 0:
       
   985                             loc_vars.append("u32 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.flag_read_req_counter;" % (server_id))
       
   986                             loc_vars_list.append(str(iecvar["NAME"]))
       
   987                         # Add if it is a "Modbus Write Request Counter" (mapped onto %MDa.b.1), so last number is a '1'
       
   988                         if iecvar["LOC"][2] == 1:
       
   989                             loc_vars.append("u32 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.flag_write_req_counter;" % (server_id))
       
   990                             loc_vars_list.append(str(iecvar["NAME"]))
       
   991                         # Add if it is a "Modbus Read Request Flag" (mapped onto %MDa.b.2), so last number is a '2'
       
   992                         if iecvar["LOC"][2] == 2:
       
   993                             loc_vars.append("u8 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.flag_read_req_flag;" % (server_id))
       
   994                             loc_vars_list.append(str(iecvar["NAME"]))
       
   995                         # Add if it is a "Modbus Write Request Counter" (mapped onto %MDa.b.3), so last number is a '3'
       
   996                         if iecvar["LOC"][2] == 3:
       
   997                             loc_vars.append("u8 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.flag_write_req_flag;" % (server_id))
       
   998                             loc_vars_list.append(str(iecvar["NAME"]))
       
   999                 
   824                 for subchild in child.IECSortedChildren():
  1000                 for subchild in child.IECSortedChildren():
   825                     new_memarea = GetTCPServerMemAreaPrinted(
  1001                     new_memarea = GetTCPServerMemAreaPrinted(self, subchild, nodeid)
   826                         self, subchild, nodeid)
       
   827                     if new_memarea is None:
  1002                     if new_memarea is None:
   828                         return [], "", False
  1003                         return [], "", False
   829                     server_memarea_list.append(new_memarea)
  1004                     server_memarea_list.append(new_memarea)
   830                     function = subchild.GetParamsAttributes()[
  1005                     function = subchild.GetParamsAttributes()[0]["children"][0]["value"]
   831                         0]["children"][0]["value"]
       
   832                     # 'ro_bits', 'rw_bits', 'ro_words' or 'rw_words'
  1006                     # 'ro_bits', 'rw_bits', 'ro_words' or 'rw_words'
   833                     memarea = modbus_memtype_dict[function][1]
  1007                     memarea = modbus_memtype_dict[function][1]
   834                     for iecvar in subchild.GetLocations():
  1008                     for iecvar in subchild.GetLocations():
   835                         # print repr(iecvar)
  1009                         if len(iecvar["LOC"]) == 4:
   836                         absloute_address = iecvar["LOC"][3]
  1010                             #print "subchild" + repr(iecvar)
   837                         start_address = int(GetCTVal(subchild, 2))
  1011                             absloute_address = iecvar["LOC"][3]
   838                         relative_addr = absloute_address - start_address
  1012                             start_address = int(GetCTVal(subchild, 2))
   839                         # test if relative address in request specified range
  1013                             relative_addr = absloute_address - start_address
   840                         if relative_addr in xrange(int(GetCTVal(subchild, 1))):
  1014                             # test if relative address in request specified range
   841                             if str(iecvar["NAME"]) not in loc_vars_list:
  1015                             if relative_addr in xrange(int(GetCTVal(subchild, 1))):
   842                                 loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.%s[%d];" % (
  1016                                 if str(iecvar["NAME"]) not in loc_vars_list:
   843                                     server_id, memarea, absloute_address))
  1017                                     loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.%s[%d];" % (
   844                                 loc_vars_list.append(str(iecvar["NAME"]))
  1018                                         server_id, memarea, absloute_address))
       
  1019                                     loc_vars_list.append(str(iecvar["NAME"]))
   845                 server_id += 1
  1020                 server_id += 1
   846             #
  1021             #
   847             if child.PlugType == "ModbusRTUslave":
  1022             if child.PlugType == "ModbusRTUslave":
   848                 rtuserver_node_count += 1
  1023                 rtuserver_node_count += 1
   849                 new_node = GetRTUSlaveNodePrinted(self, child)
  1024                 new_node = GetRTUSlaveNodePrinted(self, child)
   850                 if new_node is None:
  1025                 if new_node is None:
   851                     return [], "", False
  1026                     return [], "", False
   852                 server_node_list.append(new_node)
  1027                 server_node_list.append(new_node)
       
  1028                 #        We currently add 4 flags/counters to each Modbus server/slave
   853                 #
  1029                 #
       
  1030                 #        We add the Modbus read/write counter/flag to each Modbus slave/server
       
  1031                 #        to allow the user program to determine if the slave is being actively
       
  1032                 #        read from or written by by a remote Modbus client.
       
  1033                 for iecvar in child.GetLocations():
       
  1034                     #print "child" + repr(iecvar)
       
  1035                     if (len(iecvar["LOC"]) == 3) and (str(iecvar["NAME"]) not in loc_vars_list):
       
  1036                         # Add if it is a "Modbus Read Request Counter" (mapped onto %MDa.b.0), so last number is a '0'
       
  1037                         if iecvar["LOC"][2] == 0:
       
  1038                             loc_vars.append("u32 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.flag_read_req_counter;" % (server_id))
       
  1039                             loc_vars_list.append(str(iecvar["NAME"]))
       
  1040                         # Add if it is a "Modbus Write Request Counter" (mapped onto %MDa.b.1), so last number is a '1'
       
  1041                         if iecvar["LOC"][2] == 1:
       
  1042                             loc_vars.append("u32 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.flag_write_req_counter;" % (server_id))
       
  1043                             loc_vars_list.append(str(iecvar["NAME"]))
       
  1044                         # Add if it is a "Modbus Read Request Flag" (mapped onto %MDa.b.2), so last number is a '2'
       
  1045                         if iecvar["LOC"][2] == 2:
       
  1046                             loc_vars.append("u8 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.flag_read_req_flag;" % (server_id))
       
  1047                             loc_vars_list.append(str(iecvar["NAME"]))
       
  1048                         # Add if it is a "Modbus Write Request Counter" (mapped onto %MDa.b.3), so last number is a '3'
       
  1049                         if iecvar["LOC"][2] == 3:
       
  1050                             loc_vars.append("u8 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.flag_write_req_flag;" % (server_id))
       
  1051                             loc_vars_list.append(str(iecvar["NAME"]))
       
  1052 
   854                 for subchild in child.IECSortedChildren():
  1053                 for subchild in child.IECSortedChildren():
   855                     new_memarea = GetTCPServerMemAreaPrinted(
  1054                     new_memarea = GetTCPServerMemAreaPrinted(
   856                         self, subchild, nodeid)
  1055                         self, subchild, nodeid)
   857                     if new_memarea is None:
  1056                     if new_memarea is None:
   858                         return [], "", False
  1057                         return [], "", False
   859                     server_memarea_list.append(new_memarea)
  1058                     server_memarea_list.append(new_memarea)
   860                     function = subchild.GetParamsAttributes()[
  1059                     function = subchild.GetParamsAttributes()[0]["children"][0]["value"]
   861                         0]["children"][0]["value"]
       
   862                     # 'ro_bits', 'rw_bits', 'ro_words' or 'rw_words'
  1060                     # 'ro_bits', 'rw_bits', 'ro_words' or 'rw_words'
   863                     memarea = modbus_memtype_dict[function][1]
  1061                     memarea = modbus_memtype_dict[function][1]
   864                     for iecvar in subchild.GetLocations():
  1062                     for iecvar in subchild.GetLocations():
   865                         # print repr(iecvar)
  1063                         if len(iecvar["LOC"]) == 4:
   866                         absloute_address = iecvar["LOC"][3]
  1064                             # print repr(iecvar)
   867                         start_address = int(GetCTVal(subchild, 2))
  1065                             absloute_address = iecvar["LOC"][3]
   868                         relative_addr = absloute_address - start_address
  1066                             start_address = int(GetCTVal(subchild, 2))
   869                         # test if relative address in request specified range
  1067                             relative_addr = absloute_address - start_address
   870                         if relative_addr in xrange(int(GetCTVal(subchild, 1))):
  1068                             # test if relative address in request specified range
   871                             if str(iecvar["NAME"]) not in loc_vars_list:
  1069                             if relative_addr in xrange(int(GetCTVal(subchild, 1))):
   872                                 loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.%s[%d];" % (
  1070                                 if str(iecvar["NAME"]) not in loc_vars_list:
   873                                     server_id, memarea, absloute_address))
  1071                                     loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.%s[%d];" % (
   874                                 loc_vars_list.append(str(iecvar["NAME"]))
  1072                                         server_id, memarea, absloute_address))
       
  1073                                     loc_vars_list.append(str(iecvar["NAME"]))
   875                 server_id += 1
  1074                 server_id += 1
   876             #
  1075             #
   877             if child.PlugType == "ModbusTCPclient":
  1076             if child.PlugType == "ModbusTCPclient":
   878                 tcpclient_reqs_count += len(child.IECSortedChildren())
  1077                 tcpclient_reqs_count += len(child.IECSortedChildren())
   879                 new_node = GetTCPClientNodePrinted(self, child)
  1078                 new_node = GetTCPClientNodePrinted(self, child)