113 # datazone = modbus_function_dict[function][5] |
114 # datazone = modbus_function_dict[function][5] |
114 # 'X' for bits, 'W' for words |
115 # 'X' for bits, 'W' for words |
115 datatacc = modbus_function_dict[function][6] |
116 datatacc = modbus_function_dict[function][6] |
116 # 'Coil', 'Holding Register', 'Input Discrete' or 'Input Register' |
117 # 'Coil', 'Holding Register', 'Input Discrete' or 'Input Register' |
117 dataname = modbus_function_dict[function][7] |
118 dataname = modbus_function_dict[function][7] |
|
119 # start off with a boolean entry |
|
120 # This is a flag used to allow the user program to control when to |
|
121 # execute the Modbus request. |
|
122 # NOTE: If the Modbus request has a 'current_location' of |
|
123 # %QX1.2.3 |
|
124 # then the execution control flag will be |
|
125 # %QX1.2.3.0.0 |
|
126 # and all the Modbus registers/coils will be |
|
127 # %QX1.2.3.0 |
|
128 # %QX1.2.3.1 |
|
129 # %QX1.2.3.2 |
|
130 # .. |
|
131 # %QX1.2.3.n |
118 entries = [] |
132 entries = [] |
|
133 entries.append({ |
|
134 "name": "Exec. request flag", |
|
135 "type": LOCATION_VAR_MEMORY, |
|
136 "size": 1, # BOOL flag |
|
137 "IEC_type": "BOOL", # BOOL flag |
|
138 "var_name": "var_name", |
|
139 "location": "X" + ".".join([str(i) for i in current_location]) + ".0.0", |
|
140 "description": "MB request execution control flag", |
|
141 "children": []}) |
119 for offset in range(address, address + count): |
142 for offset in range(address, address + count): |
120 entries.append({ |
143 entries.append({ |
121 "name": dataname + " " + str(offset), |
144 "name": dataname + " " + str(offset), |
122 "type": LOCATION_VAR_MEMORY, |
145 "type": LOCATION_VAR_MEMORY, |
123 "size": datasize, |
146 "size": datasize, |
268 <xsd:attribute name="Remote_IP_Address" type="xsd:string" use="optional" default="localhost"/> |
291 <xsd:attribute name="Remote_IP_Address" type="xsd:string" use="optional" default="localhost"/> |
269 <xsd:attribute name="Remote_Port_Number" type="xsd:string" use="optional" default="502"/> |
292 <xsd:attribute name="Remote_Port_Number" type="xsd:string" use="optional" default="502"/> |
270 <xsd:attribute name="Invocation_Rate_in_ms" use="optional" default="100"> |
293 <xsd:attribute name="Invocation_Rate_in_ms" use="optional" default="100"> |
271 <xsd:simpleType> |
294 <xsd:simpleType> |
272 <xsd:restriction base="xsd:unsignedLong"> |
295 <xsd:restriction base="xsd:unsignedLong"> |
273 <xsd:minInclusive value="1"/> |
296 <xsd:minInclusive value="0"/> |
274 <xsd:maxInclusive value="2147483647"/> |
297 <xsd:maxInclusive value="2147483647"/> |
275 </xsd:restriction> |
298 </xsd:restriction> |
276 </xsd:simpleType> |
299 </xsd:simpleType> |
277 </xsd:attribute> |
300 </xsd:attribute> |
278 </xsd:complexType> |
301 </xsd:complexType> |
386 <xsd:attribute name="Parity" type="xsd:string" use="optional" default="even"/> |
409 <xsd:attribute name="Parity" type="xsd:string" use="optional" default="even"/> |
387 <xsd:attribute name="Stop_Bits" type="xsd:string" use="optional" default="1"/> |
410 <xsd:attribute name="Stop_Bits" type="xsd:string" use="optional" default="1"/> |
388 <xsd:attribute name="Invocation_Rate_in_ms" use="optional" default="100"> |
411 <xsd:attribute name="Invocation_Rate_in_ms" use="optional" default="100"> |
389 <xsd:simpleType> |
412 <xsd:simpleType> |
390 <xsd:restriction base="xsd:integer"> |
413 <xsd:restriction base="xsd:integer"> |
391 <xsd:minInclusive value="1"/> |
414 <xsd:minInclusive value="0"/> |
392 <xsd:maxInclusive value="2147483647"/> |
415 <xsd:maxInclusive value="2147483647"/> |
393 </xsd:restriction> |
416 </xsd:restriction> |
394 </xsd:simpleType> |
417 </xsd:simpleType> |
395 </xsd:attribute> |
418 </xsd:attribute> |
396 </xsd:complexType> |
419 </xsd:complexType> |
596 # for e.g., convert the tuple (0, 3, 4) to "0.3.4" |
619 # for e.g., convert the tuple (0, 3, 4) to "0.3.4" |
597 |
620 |
598 for i in range(0, len(IPServer_port_numbers) - 1): |
621 for i in range(0, len(IPServer_port_numbers) - 1): |
599 for j in range(i + 1, len(IPServer_port_numbers)): |
622 for j in range(i + 1, len(IPServer_port_numbers)): |
600 if IPServer_port_numbers[i][1] == IPServer_port_numbers[j][1]: |
623 if IPServer_port_numbers[i][1] == IPServer_port_numbers[j][1]: |
601 self.GetCTRoot().logger.write_warning( |
624 error_message = _("Error: Modbus/IP Servers %{a1}.x and %{a2}.x use the same port number {a3}.\n").format( |
602 _("Error: Modbus/IP Servers %{a1}.x and %{a2}.x use the same port number {a3}.\n"). |
625 a1=_lt_to_str(IPServer_port_numbers[i][0]), |
603 format( |
626 a2=_lt_to_str(IPServer_port_numbers[j][0]), |
604 a1=_lt_to_str(IPServer_port_numbers[i][0]), |
627 a3=IPServer_port_numbers[j][1]) |
605 a2=_lt_to_str(IPServer_port_numbers[j][0]), |
628 self.FatalError(error_message) |
606 a3=IPServer_port_numbers[j][1])) |
629 #self.GetCTRoot().logger.write_warning(error_message) |
607 raise Exception |
630 #raise Exception |
608 # TODO: return an error code instead of raising an |
|
609 # exception |
|
610 |
631 |
611 # Determine the current location in Beremiz's project configuration |
632 # Determine the current location in Beremiz's project configuration |
612 # tree |
633 # tree |
613 current_location = self.GetCurrentLocation() |
634 current_location = self.GetCurrentLocation() |
614 |
635 |
718 return [], "", False |
739 return [], "", False |
719 client_request_list.append(new_req) |
740 client_request_list.append(new_req) |
720 for iecvar in subchild.GetLocations(): |
741 for iecvar in subchild.GetLocations(): |
721 # absloute address - start address |
742 # absloute address - start address |
722 relative_addr = iecvar["LOC"][3] - int(GetCTVal(subchild, 3)) |
743 relative_addr = iecvar["LOC"][3] - int(GetCTVal(subchild, 3)) |
723 # test if relative address in request specified range |
744 # test if the located variable |
724 if relative_addr in xrange(int(GetCTVal(subchild, 2))): |
745 # (a) has relative address in request specified range |
|
746 # AND is NOT |
|
747 # (b) is a control flag added by this modbus plugin |
|
748 # to control its execution at runtime. |
|
749 # Currently, we only add the "Execution Control Flag" |
|
750 # to each client request (one flag per request) |
|
751 # to control when to execute the request (if not executed periodically) |
|
752 # While all Modbus registers/coils are mapped onto a location |
|
753 # with 4 numbers (e.g. %QX0.1.2.55), this control flag is mapped |
|
754 # onto a location with 4 numbers (e.g. %QX0.1.2.0.0), where the last |
|
755 # two numbers are always '0.0', and the first two identify the request. |
|
756 # In the following if, we check for this condition by checking |
|
757 # if their are at least 4 or more number in the location's address. |
|
758 if ( relative_addr in xrange(int(GetCTVal(subchild, 2))) # condition (a) explained above |
|
759 and len(iecvar["LOC"]) < 5): # condition (b) explained above |
725 if str(iecvar["NAME"]) not in loc_vars_list: |
760 if str(iecvar["NAME"]) not in loc_vars_list: |
726 loc_vars.append( |
761 loc_vars.append( |
727 "u16 *" + str(iecvar["NAME"]) + " = &client_requests[%d].plcv_buffer[%d];" % (client_requestid, relative_addr)) |
762 "u16 *" + str(iecvar["NAME"]) + " = &client_requests[%d].plcv_buffer[%d];" % (client_requestid, relative_addr)) |
|
763 loc_vars_list.append(str(iecvar["NAME"])) |
|
764 # Now add the located variable in case it is a flag (condition (b) above |
|
765 if len(iecvar["LOC"]) >= 5: # condition (b) explained above |
|
766 if str(iecvar["NAME"]) not in loc_vars_list: |
|
767 loc_vars.append( |
|
768 "u16 *" + str(iecvar["NAME"]) + " = &client_requests[%d].flag_exec_req;" % (client_requestid)) |
728 loc_vars_list.append(str(iecvar["NAME"])) |
769 loc_vars_list.append(str(iecvar["NAME"])) |
729 client_requestid += 1 |
770 client_requestid += 1 |
730 tcpclient_node_count += 1 |
771 tcpclient_node_count += 1 |
731 client_nodeid += 1 |
772 client_nodeid += 1 |
732 # |
773 # |
743 return [], "", False |
784 return [], "", False |
744 client_request_list.append(new_req) |
785 client_request_list.append(new_req) |
745 for iecvar in subchild.GetLocations(): |
786 for iecvar in subchild.GetLocations(): |
746 # absloute address - start address |
787 # absloute address - start address |
747 relative_addr = iecvar["LOC"][3] - int(GetCTVal(subchild, 3)) |
788 relative_addr = iecvar["LOC"][3] - int(GetCTVal(subchild, 3)) |
748 # test if relative address in request specified range |
789 # test if the located variable |
749 if relative_addr in xrange(int(GetCTVal(subchild, 2))): |
790 # (a) has relative address in request specified range |
|
791 # AND is NOT |
|
792 # (b) is a control flag added by this modbus plugin |
|
793 # to control its execution at runtime. |
|
794 # Currently, we only add the "Execution Control Flag" |
|
795 # to each client request (one flag per request) |
|
796 # to control when to execute the request (if not executed periodically) |
|
797 # While all Modbus registers/coils are mapped onto a location |
|
798 # with 4 numbers (e.g. %QX0.1.2.55), this control flag is mapped |
|
799 # onto a location with 4 numbers (e.g. %QX0.1.2.0.0), where the last |
|
800 # two numbers are always '0.0', and the first two identify the request. |
|
801 # In the following if, we check for this condition by checking |
|
802 # if their are at least 4 or more number in the location's address. |
|
803 if ( relative_addr in xrange(int(GetCTVal(subchild, 2))) # condition (a) explained above |
|
804 and len(iecvar["LOC"]) < 5): # condition (b) explained above |
750 if str(iecvar["NAME"]) not in loc_vars_list: |
805 if str(iecvar["NAME"]) not in loc_vars_list: |
751 loc_vars.append( |
806 loc_vars.append( |
752 "u16 *" + str(iecvar["NAME"]) + " = &client_requests[%d].plcv_buffer[%d];" % (client_requestid, relative_addr)) |
807 "u16 *" + str(iecvar["NAME"]) + " = &client_requests[%d].plcv_buffer[%d];" % (client_requestid, relative_addr)) |
|
808 loc_vars_list.append(str(iecvar["NAME"])) |
|
809 # Now add the located variable in case it is a flag (condition (b) above |
|
810 if len(iecvar["LOC"]) >= 5: # condition (b) explained above |
|
811 if str(iecvar["NAME"]) not in loc_vars_list: |
|
812 loc_vars.append( |
|
813 "u16 *" + str(iecvar["NAME"]) + " = &client_requests[%d].flag_exec_req;" % (client_requestid)) |
753 loc_vars_list.append(str(iecvar["NAME"])) |
814 loc_vars_list.append(str(iecvar["NAME"])) |
754 client_requestid += 1 |
815 client_requestid += 1 |
755 rtuclient_node_count += 1 |
816 rtuclient_node_count += 1 |
756 client_nodeid += 1 |
817 client_nodeid += 1 |
757 nodeid += 1 |
818 nodeid += 1 |