450 # These flags are mapped onto located variables and therefore available to the user programs |
450 # These flags are mapped onto located variables and therefore available to the user programs |
451 # May be used to detect communication errors. |
451 # May be used to detect communication errors. |
452 # execute the Modbus request. |
452 # execute the Modbus request. |
453 # NOTE: If the Modbus slave has a 'current_location' of |
453 # NOTE: If the Modbus slave has a 'current_location' of |
454 # %QX1.2 |
454 # %QX1.2 |
455 # then the "Modbus Read Request Counter" will be |
455 # then the "Modbus Read Request Counter" will be %MD1.2.0 |
456 # %MD1.2.0 |
456 # then the "Modbus Write Request Counter" will be %MD1.2.1 |
457 # then the "Modbus Write Request Counter" will be |
457 # then the "Modbus Read Request Flag" will be %MD1.2.2 |
458 # %MD1.2.1 |
458 # then the "Modbus Write Request Flag" will be %MD1.2.3 |
459 # |
459 # |
460 # Note that any MemoryArea contained under this server/slave |
460 # Note that any MemoryArea contained under this server/slave |
461 # will ocupy the locations of type |
461 # will ocupy the locations of type |
462 # %MX or %MW |
462 # %MX or %MW |
463 # which will never clash with the %MD used here. |
463 # which will never clash with the %MD used here. |
465 # will ocupy locations with |
465 # will ocupy locations with |
466 # %M1.2.a.b (with a and b being numbers in range 0, 1, ...) |
466 # %M1.2.a.b (with a and b being numbers in range 0, 1, ...) |
467 # and therefore never ocupy the locations |
467 # and therefore never ocupy the locations |
468 # %M1.2.0 |
468 # %M1.2.0 |
469 # %M1.2.1 |
469 # %M1.2.1 |
|
470 # %M1.2.2 |
|
471 # %M1.2.3 |
470 # used by the following flags/counters. |
472 # used by the following flags/counters. |
471 entries = [] |
473 entries = [] |
472 entries.append({ |
474 entries.append({ |
473 "name": "Modbus Read Request Counter", |
475 "name": "Modbus Read Request Counter", |
474 "type": LOCATION_VAR_MEMORY, |
476 "type": LOCATION_VAR_MEMORY, |
484 "size": 32, # UDINT flag |
486 "size": 32, # UDINT flag |
485 "IEC_type": "UDINT", # UDINT flag |
487 "IEC_type": "UDINT", # UDINT flag |
486 "var_name": "var_name", |
488 "var_name": "var_name", |
487 "location": "D" + ".".join([str(i) for i in current_location]) + ".1", |
489 "location": "D" + ".".join([str(i) for i in current_location]) + ".1", |
488 "description": "Modbus write request counter", |
490 "description": "Modbus write request counter", |
|
491 "children": []}) |
|
492 entries.append({ |
|
493 "name": "Modbus Read Request Flag", |
|
494 "type": LOCATION_VAR_MEMORY, |
|
495 "size": 1, # BOOL flag |
|
496 "IEC_type": "BOOL", # BOOL flag |
|
497 "var_name": "var_name", |
|
498 "location": "X" + ".".join([str(i) for i in current_location]) + ".2", |
|
499 "description": "Modbus read request flag", |
|
500 "children": []}) |
|
501 entries.append({ |
|
502 "name": "Modbus write Request Flag", |
|
503 "type": LOCATION_VAR_MEMORY, |
|
504 "size": 1, # BOOL flag |
|
505 "IEC_type": "BOOL", # BOOL flag |
|
506 "var_name": "var_name", |
|
507 "location": "X" + ".".join([str(i) for i in current_location]) + ".3", |
|
508 "description": "Modbus write request flag", |
489 "children": []}) |
509 "children": []}) |
490 # recursively call all the Memory Areas under this Modbus server/save |
510 # recursively call all the Memory Areas under this Modbus server/save |
491 # i.e., all the children objects which will be of class _MemoryAreaPlug |
511 # i.e., all the children objects which will be of class _MemoryAreaPlug |
492 for child in self.IECSortedChildren(): |
512 for child in self.IECSortedChildren(): |
493 entries.append(child.GetVariableLocationTree()) |
513 entries.append(child.GetVariableLocationTree()) |
687 # These flags are mapped onto located variables and therefore available to the user programs |
707 # These flags are mapped onto located variables and therefore available to the user programs |
688 # May be used to detect communication errors. |
708 # May be used to detect communication errors. |
689 # execute the Modbus request. |
709 # execute the Modbus request. |
690 # NOTE: If the Modbus slave has a 'current_location' of |
710 # NOTE: If the Modbus slave has a 'current_location' of |
691 # %QX1.2 |
711 # %QX1.2 |
692 # then the "Modbus Read Request Counter" will be |
712 # then the "Modbus Read Request Counter" will be %MD1.2.0 |
693 # %MD1.2.0 |
713 # then the "Modbus Write Request Counter" will be %MD1.2.1 |
694 # then the "Modbus Write Request Counter" will be |
714 # then the "Modbus Read Request Flag" will be %MD1.2.2 |
695 # %MD1.2.1 |
715 # then the "Modbus Write Request Flag" will be %MD1.2.3 |
696 # |
716 # |
697 # Note that any MemoryArea contained under this server/slave |
717 # Note that any MemoryArea contained under this server/slave |
698 # will ocupy the locations of type |
718 # will ocupy the locations of type |
699 # %MX or %MW |
719 # %MX or %MW |
700 # which will never clash with the %MD used here. |
720 # which will never clash with the %MD used here. |
702 # will ocupy locations with |
722 # will ocupy locations with |
703 # %M1.2.a.b (with a and b being numbers in range 0, 1, ...) |
723 # %M1.2.a.b (with a and b being numbers in range 0, 1, ...) |
704 # and therefore never ocupy the locations |
724 # and therefore never ocupy the locations |
705 # %M1.2.0 |
725 # %M1.2.0 |
706 # %M1.2.1 |
726 # %M1.2.1 |
|
727 # %M1.2.2 |
|
728 # %M1.2.3 |
707 # used by the following flags/counters. |
729 # used by the following flags/counters. |
708 entries = [] |
730 entries = [] |
709 entries.append({ |
731 entries.append({ |
710 "name": "Modbus Read Request Counter", |
732 "name": "Modbus Read Request Counter", |
711 "type": LOCATION_VAR_MEMORY, |
733 "type": LOCATION_VAR_MEMORY, |
721 "size": 32, # UDINT flag |
743 "size": 32, # UDINT flag |
722 "IEC_type": "UDINT", # UDINT flag |
744 "IEC_type": "UDINT", # UDINT flag |
723 "var_name": "var_name", |
745 "var_name": "var_name", |
724 "location": "D" + ".".join([str(i) for i in current_location]) + ".1", |
746 "location": "D" + ".".join([str(i) for i in current_location]) + ".1", |
725 "description": "Modbus write request counter", |
747 "description": "Modbus write request counter", |
|
748 "children": []}) |
|
749 entries.append({ |
|
750 "name": "Modbus Read Request Flag", |
|
751 "type": LOCATION_VAR_MEMORY, |
|
752 "size": 1, # BOOL flag |
|
753 "IEC_type": "BOOL", # BOOL flag |
|
754 "var_name": "var_name", |
|
755 "location": "X" + ".".join([str(i) for i in current_location]) + ".2", |
|
756 "description": "Modbus read request flag", |
|
757 "children": []}) |
|
758 entries.append({ |
|
759 "name": "Modbus write Request Flag", |
|
760 "type": LOCATION_VAR_MEMORY, |
|
761 "size": 1, # BOOL flag |
|
762 "IEC_type": "BOOL", # BOOL flag |
|
763 "var_name": "var_name", |
|
764 "location": "X" + ".".join([str(i) for i in current_location]) + ".3", |
|
765 "description": "Modbus write request flag", |
726 "children": []}) |
766 "children": []}) |
727 # recursively call all the Memory Areas under this Modbus server/save |
767 # recursively call all the Memory Areas under this Modbus server/save |
728 # i.e., all the children objects which will be of class _MemoryAreaPlug |
768 # i.e., all the children objects which will be of class _MemoryAreaPlug |
729 for child in self.IECSortedChildren(): |
769 for child in self.IECSortedChildren(): |
730 entries.append(child.GetVariableLocationTree()) |
770 entries.append(child.GetVariableLocationTree()) |
922 tcpserver_node_count += 1 |
962 tcpserver_node_count += 1 |
923 new_node = GetTCPServerNodePrinted(self, child) |
963 new_node = GetTCPServerNodePrinted(self, child) |
924 if new_node is None: |
964 if new_node is None: |
925 return [], "", False |
965 return [], "", False |
926 server_node_list.append(new_node) |
966 server_node_list.append(new_node) |
927 # We currently add 2 flags/counters to each Modbus server/slave |
967 # We currently add 4 flags/counters to each Modbus server/slave |
928 # |
968 # |
929 # TODO: fix comment |
969 # We add the Modbus read/write counter/flag to each Modbus slave/server |
930 # We add the "Execution Control Flag" to each client request (one flag per request) |
970 # to allow the user program to determine if the slave is being actively |
931 # to allow the user program to control when to execute the request (if not executed periodically) |
971 # read from or written by by a remote Modbus client. |
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(): |
972 for iecvar in child.GetLocations(): |
939 #print "child" + repr(iecvar) |
973 #print "child" + repr(iecvar) |
940 if (len(iecvar["LOC"]) == 3) and (str(iecvar["NAME"]) not in loc_vars_list): |
974 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' |
975 # 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: |
976 if iecvar["LOC"][2] == 0: |
943 loc_vars.append("u32 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.flag_read_req_counter;" % (server_id)) |
977 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"])) |
978 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' |
979 # 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: |
980 if iecvar["LOC"][2] == 1: |
947 loc_vars.append("u32 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.flag_write_req_counter;" % (server_id)) |
981 loc_vars.append("u32 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.flag_write_req_counter;" % (server_id)) |
|
982 loc_vars_list.append(str(iecvar["NAME"])) |
|
983 # Add if it is a "Modbus Read Request Flag" (mapped onto %MDa.b.2), so last number is a '2' |
|
984 if iecvar["LOC"][2] == 2: |
|
985 loc_vars.append("u8 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.flag_read_req_flag;" % (server_id)) |
|
986 loc_vars_list.append(str(iecvar["NAME"])) |
|
987 # Add if it is a "Modbus Write Request Counter" (mapped onto %MDa.b.3), so last number is a '3' |
|
988 if iecvar["LOC"][2] == 3: |
|
989 loc_vars.append("u8 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.flag_write_req_flag;" % (server_id)) |
948 loc_vars_list.append(str(iecvar["NAME"])) |
990 loc_vars_list.append(str(iecvar["NAME"])) |
949 |
991 |
950 for subchild in child.IECSortedChildren(): |
992 for subchild in child.IECSortedChildren(): |
951 new_memarea = GetTCPServerMemAreaPrinted(self, subchild, nodeid) |
993 new_memarea = GetTCPServerMemAreaPrinted(self, subchild, nodeid) |
952 if new_memarea is None: |
994 if new_memarea is None: |
973 rtuserver_node_count += 1 |
1015 rtuserver_node_count += 1 |
974 new_node = GetRTUSlaveNodePrinted(self, child) |
1016 new_node = GetRTUSlaveNodePrinted(self, child) |
975 if new_node is None: |
1017 if new_node is None: |
976 return [], "", False |
1018 return [], "", False |
977 server_node_list.append(new_node) |
1019 server_node_list.append(new_node) |
|
1020 # We currently add 4 flags/counters to each Modbus server/slave |
978 # |
1021 # |
|
1022 # We add the Modbus read/write counter/flag to each Modbus slave/server |
|
1023 # to allow the user program to determine if the slave is being actively |
|
1024 # read from or written by by a remote Modbus client. |
|
1025 for iecvar in child.GetLocations(): |
|
1026 #print "child" + repr(iecvar) |
|
1027 if (len(iecvar["LOC"]) == 3) and (str(iecvar["NAME"]) not in loc_vars_list): |
|
1028 # Add if it is a "Modbus Read Request Counter" (mapped onto %MDa.b.0), so last number is a '0' |
|
1029 if iecvar["LOC"][2] == 0: |
|
1030 loc_vars.append("u32 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.flag_read_req_counter;" % (server_id)) |
|
1031 loc_vars_list.append(str(iecvar["NAME"])) |
|
1032 # Add if it is a "Modbus Write Request Counter" (mapped onto %MDa.b.1), so last number is a '1' |
|
1033 if iecvar["LOC"][2] == 1: |
|
1034 loc_vars.append("u32 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.flag_write_req_counter;" % (server_id)) |
|
1035 loc_vars_list.append(str(iecvar["NAME"])) |
|
1036 # Add if it is a "Modbus Read Request Flag" (mapped onto %MDa.b.2), so last number is a '2' |
|
1037 if iecvar["LOC"][2] == 2: |
|
1038 loc_vars.append("u8 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.flag_read_req_flag;" % (server_id)) |
|
1039 loc_vars_list.append(str(iecvar["NAME"])) |
|
1040 # Add if it is a "Modbus Write Request Counter" (mapped onto %MDa.b.3), so last number is a '3' |
|
1041 if iecvar["LOC"][2] == 3: |
|
1042 loc_vars.append("u8 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.flag_write_req_flag;" % (server_id)) |
|
1043 loc_vars_list.append(str(iecvar["NAME"])) |
|
1044 |
979 for subchild in child.IECSortedChildren(): |
1045 for subchild in child.IECSortedChildren(): |
980 new_memarea = GetTCPServerMemAreaPrinted( |
1046 new_memarea = GetTCPServerMemAreaPrinted( |
981 self, subchild, nodeid) |
1047 self, subchild, nodeid) |
982 if new_memarea is None: |
1048 if new_memarea is None: |
983 return [], "", False |
1049 return [], "", False |