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) |