|
rllib
1
|
#include <rlsiemenstcp.h>


Classes | |
| struct | FA |
| struct | FH |
| struct | IH |
| struct | WA |
| struct | WH |
Public Types | |
| enum | ORG { ORG_DB = 1, ORG_M = 2, ORG_E = 3, ORG_A = 4, ORG_PEPA = 5, ORG_Z = 6, ORG_T = 7 } |
| enum | PLC_TYPE { ANY_SIEMENS_COMPATIBLE_PLC = 1000, S7_200 = 1, S7_300 = 2, S7_400 = 3, S5 = 4, RACK_SLOT = 5, S7_1200 = 6, LOGO = 7 } |
| enum | SiemensFunctionCodes { WriteBit = 1, WriteByte = 2 } |
Public Types inherited from rlSocket | |
| enum | SocketEnum { SOCKET_ERR = -1, SETSOCKOPT_ERR = -2, LISTEN_ERR = -3, ACCEPT_ERR = -4, INET_ADDR_ERR = -5, CONNECT_ERR = -6, PORT_ERR = -7 } |
Public Member Functions | |
| rlSiemensTCP (const char *adr, int _plc_type=rlSiemensTCP::ANY_SIEMENS_COMPATIBLE_PLC, int _fetch_write=1, int function=-1, int rack_slot=-1) | |
| virtual | ~rlSiemensTCP () |
| int | getDefaultConnectBlock (unsigned char *connect_block) |
| int | setConnectBlock (const unsigned char *connect_block) |
| int | getConnectBlock (unsigned char *connect_block) |
| int | write (int org, int dbnr, int start_adr, int length, const unsigned char *buf, int function=WriteByte) |
| int | fetch (int org, int dbnr, int start_adr, int length, unsigned char *buf) |
Public Member Functions inherited from rlSocket | |
| rlSocket (const char *adr, int port, int active) | |
| rlSocket (int socket) | |
| virtual | ~rlSocket () |
| void | setAdr (const char *adr) |
| void | setPort (int port) |
| int | getPort () |
| void | setActive (int active) |
| int | read (void *buf, int len, int timeout=0) |
| int | readStr (char *buf, int len, int timeout=0) |
| int | readHttpHeader (rlString *header, int timeout=0) |
| int | write (const void *buf, int len) |
| int | printf (const char *format,...) |
| int | connect () |
| int | disconnect () |
| int | select (int timeout=0) |
| int | isConnected () |
| int | setIPVersion (int version) |
| int | getIPVersion () |
| int | sendProcessViewBrowserButtonEvent (int id) |
| int | rlGetsockopt (int level, int optname) |
| int | rlSetsockopt (int level, int optname) |
| int | readHttpContentLength (int timeout) |
Private Member Functions | |
| void | doConnect () |
| int | read_iso (unsigned char *buf) |
| int | write_iso (unsigned char *buf, int len) |
| int | getOrg (int org) |
| int | write_bit (int &i, int org, int dbnr, int start_adr, int len, const unsigned char *buf) |
| int | write_byte (int &i, int org, int dbnr, int start_adr, int length, const unsigned char *buf) |
Private Attributes | |
| WH | wh |
| WA | wa |
| FH | fh |
| FA | fa |
| IH | ih |
| int | function |
| int | rack_slot |
| int | plc_type |
| int | fetch_write |
| unsigned char | pdu [2048] |
| int | use_cb |
| unsigned char | cb [22] |
Additional Inherited Members | |
Static Public Member Functions inherited from rlSocket | |
| static int | rlGetsockopt (int sockfd, int level, int optname, void *optval, int *optlen) |
| static int | rlSetsockopt (int sockfd, int level, int optname, const void *optval, int optlen) |
Public Attributes inherited from rlSocket | |
| int | s |
| unsigned char | sockaddr [16+48] |
class for communication with Siemens PLC's via TCP
(1) There is the old Fetch/Write protocol from the old S5 PLC (fetch_write=1).
(2) And there is the current Siemens PLC protocol introduced with the S7 series of PLC (fetch_write=0).
According to http://www.ietf.org/rfc/rfc0905.txt the client will send a connection request to the PLC after it has establisched a TCP connection().
Here is a example connect_block for a Siemens S7 PLC (CBxx in hex): CB00= 3, ISO_HEADER_VERSION CB01= 0, ISO_HEADER_RESERVED CB02= 0, ISO_HEADER_LENGHT_HIGH CB03=16, ISO_HEADER_LENGHT_LOW = 22 Byte (hex 16) CB04=11, Length Indicator Field = 17 dec = 22 byte_total_length - 1 byte_length_indicator - 4 byte_ISO_HEADER CB05=E0, Connection Request Code (Bits 8-5) 1110=E, Initial Credit Allocation (Bits 4-1) Class 0 CB06= 0, DESTINATION-REF-HIGH CB07= 0, DESTINATION-REF-LOW CB08= 0, SOURCE-REF-HIGH CB09= 1, SOURCE-REF-LOW CB10= 0, Class and Option CB11=C1, Identifier: Calling TSAP will follow CB12= 2, Parameter Length, 2 byte will follow CB13= 1, Remote TSAP, free to choose on client side (1=PG,2=OP,3=Step7Basic) suggested CB14= 0, Remote TSAP, free to choose on client side (upper_3_bit_is_rack / lower_5_bit_is_slot) suggested CB15=C2, Identifier: Called TSAP will follow CB16= 2, Parameter Length, 2 byte will follow CB17= 1, Local TSAP, set within Step7 = 1 (1=PG,2=OP,3=Step7Basic) CB18= 0, Local TSAP, set within Step7 = 0...connectionN (upper_3_bit_is_rack / lower_5_bit_is_slot) CB19=C0, Identifier: Maximum TPDU size will follow CB20= 1, Parameter Length, 1 byte will follow CB21= 9, max 512 octets
For the different PLC types the connect_block looks as follows:
s7_200 = {3,0,0,16,0x11,0xE0,0x00,0x00,0x00,0x01,0x00,0xC1,2,'M','W',0xC2,2,'M','W',0xC0,1,9}
s7_300 = {3,0,0,16,0x11,0xE0,0x00,0x00,0x00,0x01,0x00,0xC1,2, 1,0 ,0xC2,2, 1,2 ,0xC0,1,9} on S7_300 slot of cpu is always 2
s7_400 = {3,0,0,16,0x11,0xE0,0x00,0x00,0x00,0x01,0x00,0xC1,2, 1,0 ,0xC2,2, 1,3 ,0xC0,1,9} on S7_400 slot of cpu is always 3
s7_1200 = {3,0,0,16,0x11,0xE0,0x00,0x00,0x00,0x01,0x00,0xC1,2, 1,0 ,0xC2,2, 1,0 ,0xC0,1,9} slot may be 0 || 1 and TSAP 03.01 || 10.00
s7_logo = {3,0,0,22,0x11,0xE0,0x00,0x00,0x00,0x01,0x00,0xC1,2, 2,0 ,0xC2,2, 2,0 ,0xC0,1,9}
For S7_200 and S7_1200 read: (only symbolic access to DB1)
http://support.automation.siemens.com/WW/llisapi.dll?func=cslib.csinfo&lang=en&objid=21601611&caller=viewAccording to the Remote TSAP Siemens makes the following statement: ###################################################################################### Remote TSAP (Remote Transport Service Access Point, entfernter Dienstzugangspunkt) The representation is the same as with the Local TSAP, but the second byte has another meaning:
When you use our rlSiemensTCP class you can do it as follows:
unsigned char cb[22]; rlSiemensTCP *plc = new rlSiemensTCP(adr); plc->getDefaultConnectBlock(cb); cb[13] = 1; // set 1 Byte of Remote TSAP cb[14] = 0; // set 2 Byte of Remote TSAP cb[17] = 1; // set Local TSAP of the PLC to the cb[18] = 0; // configuration done within Step 7 plc->setConnectBlock(cb);
Now you can read/write the PLC.
The following matrix shows some combinations:
--------------------------------------------
| CB13 CB14 CB17 CB18
--------------------------------------------
S7_200 | 'M' 'W' 'M' 'W'
--------------------------------------------
S7_300 | 1 0 1 2
--------------------------------------------
S7_400 | 1 0 1 3
--------------------------------------------
S7_1200 | 1 0 1 0
--------------------------------------------
S7_logo 0BA7 | 2 0 2 0
--------------------------------------------CB17 = (1=PG,2=OP,3=Step7Basic) CB18 = (upper_3_bit_is_rack / lower_5_bit_is_slot) Thus the above would be: A TSAP within Step 7 of 10.00 results in: cb[17] = PG; cb[18] = 0; // rack=0 slot=0 A TSAP within Step 7 of 10.01 results in: cb[17] = PG; cb[18] = 1; // rack=0 slot=1 A TSAP within Step 7 of 10.02 results in: cb[17] = PG; cb[18] = 2; // rack=0 slot=2 A TSAP within Step 7 of 10.03 results in: cb[17] = PG; cb[18] = 3; // rack=0 slot=3
You may use rlSiemensTCP with the individual plc_type for conveniance. But you can set the whole connect_block and use ANY_SIEMENS_COMPATIBLE_PLC.
Please use Wireshark or tcpdump if the settings of the above matrix do not work for you. Send us your results.
PS: Still wondering about 'M' 'W' on S7-200
Definition at line 130 of file rlsiemenstcp.h.
| enum rlSiemensTCP::ORG |
| Enumerator | |
|---|---|
| ORG_DB | |
| ORG_M | |
| ORG_E | |
| ORG_A | |
| ORG_PEPA | |
| ORG_Z | |
| ORG_T | |
Definition at line 133 of file rlsiemenstcp.h.
| Enumerator | |
|---|---|
| ANY_SIEMENS_COMPATIBLE_PLC | |
| S7_200 | |
| S7_300 | |
| S7_400 | |
| S5 | |
| RACK_SLOT | |
| S7_1200 | |
| LOGO | |
Definition at line 143 of file rlsiemenstcp.h.
| Enumerator | |
|---|---|
| WriteBit | |
| WriteByte | |
Definition at line 154 of file rlsiemenstcp.h.
| rlSiemensTCP::rlSiemensTCP | ( | const char * | adr, |
| int | _plc_type = rlSiemensTCP::ANY_SIEMENS_COMPATIBLE_PLC, |
||
| int | _fetch_write = 1, |
||
| int | function = -1, |
||
| int | rack_slot = -1 |
||
| ) |
Definition at line 31 of file rlsiemenstcp.cpp.
|
virtual |
Definition at line 45 of file rlsiemenstcp.cpp.
|
private |
Definition at line 71 of file rlsiemenstcp.cpp.
| int rlSiemensTCP::fetch | ( | int | org, |
| int | dbnr, | ||
| int | start_adr, | ||
| int | length, | ||
| unsigned char * | buf | ||
| ) |
Definition at line 434 of file rlsiemenstcp.cpp.
| int rlSiemensTCP::getConnectBlock | ( | unsigned char * | connect_block | ) |
Definition at line 65 of file rlsiemenstcp.cpp.
| int rlSiemensTCP::getDefaultConnectBlock | ( | unsigned char * | connect_block | ) |
Definition at line 50 of file rlsiemenstcp.cpp.
|
private |
Definition at line 181 of file rlsiemenstcp.cpp.
|
private |
Definition at line 561 of file rlsiemenstcp.cpp.
| int rlSiemensTCP::setConnectBlock | ( | const unsigned char * | connect_block | ) |
Definition at line 58 of file rlsiemenstcp.cpp.
| int rlSiemensTCP::write | ( | int | org, |
| int | dbnr, | ||
| int | start_adr, | ||
| int | length, | ||
| const unsigned char * | buf, | ||
| int | function = WriteByte |
||
| ) |
Definition at line 212 of file rlsiemenstcp.cpp.
|
private |
Definition at line 367 of file rlsiemenstcp.cpp.
|
private |
Definition at line 403 of file rlsiemenstcp.cpp.
|
private |
Definition at line 607 of file rlsiemenstcp.cpp.
|
private |
Definition at line 252 of file rlsiemenstcp.h.
|
private |
Definition at line 245 of file rlsiemenstcp.h.
|
private |
Definition at line 249 of file rlsiemenstcp.h.
|
private |
Definition at line 244 of file rlsiemenstcp.h.
|
private |
Definition at line 247 of file rlsiemenstcp.h.
|
private |
Definition at line 246 of file rlsiemenstcp.h.
|
private |
Definition at line 250 of file rlsiemenstcp.h.
|
private |
Definition at line 248 of file rlsiemenstcp.h.
|
private |
Definition at line 247 of file rlsiemenstcp.h.
|
private |
Definition at line 251 of file rlsiemenstcp.h.
|
private |
Definition at line 243 of file rlsiemenstcp.h.
|
private |
Definition at line 242 of file rlsiemenstcp.h.
1.8.14