rllib  1
rlsiemenstcp.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  rlsiemenstcp.cpp - description
3  -------------------
4  begin : Mon Mar 08 2004
5  copyright : (C) 2004 by R. Lehrig
6  email : lehrig@t-online.de
7 
8  S7_200 update : Wed Mar 21 2007
9  copyright : (C) 2007 by Aljosa Merljak
10  Email : aljosa.merljak@datapan.si
11  ***************************************************************************/
12 
13 /***************************************************************************
14  * *
15  * This library is free software; you can redistribute it and/or modify *
16  * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as *
17  * published by the Free Software Foundation *
18  * *
19  ***************************************************************************/
20 
21 #include "rlsiemenstcp.h"
22 #include "rlwthread.h"
23 #include "rlcutil.h"
24 #include <stdio.h>
25 #include <string.h>
26 #define TIMEOUT 2000
27 #define ISO_PORT 102
28 
29 extern int rlDebugPrintfState;
30 
31 rlSiemensTCP::rlSiemensTCP(const char *a, int _plc_type, int _fetch_write, int _function, int _rack_slot)
32  :rlSocket(a,ISO_PORT,1)
33 {
34  plc_type = _plc_type;
35  fetch_write = _fetch_write;
36  function = _function;
37  rack_slot = _rack_slot;
38  //doConnect();
39  use_cb = 0;
40  unsigned char connect_block[22];
41  getDefaultConnectBlock(connect_block);
42  memcpy(cb,connect_block,sizeof(cb));
43 }
44 
46 {
48 }
49 
50 int rlSiemensTCP::getDefaultConnectBlock(unsigned char *connect_block)
51 {
52  static const unsigned char default_connect_block[] =
53  {3,0,0,22,0x11,0xE0,0x00,0x00,0x00,0x01,0x00,0xC1,2,1 ,0 ,0xC2,2,0 ,1 ,0xC0,1,9};
54  memcpy(connect_block,default_connect_block,sizeof(default_connect_block));
55  return 22;
56 }
57 
58 int rlSiemensTCP::setConnectBlock(const unsigned char *connect_block)
59 {
60  memcpy(cb,connect_block,sizeof(cb));
61  use_cb = 1;
62  return 0;
63 }
64 
65 int rlSiemensTCP::getConnectBlock(unsigned char *connect_block)
66 {
67  memcpy(connect_block,cb,sizeof(cb));
68  return 0;
69 }
70 
72 {
73  int i,i2,ret,length;
74  static const unsigned char s7_200_connect_block[] =
75  {3,0,0,22,0x11,0xE0,0x00,0x00,0x00,0x01,0x00,0xC1,2,'M','W',0xC2,2,'M','W',0xC0,1,9};
76  static const unsigned char s7_300_connect_block[] =
77  {3,0,0,22,0x11,0xE0,0x00,0x00,0x00,0x01,0x00,0xC1,2,1 ,0 ,0xC2,2,1 ,2 ,0xC0,1,9};
78  static const unsigned char s7_400_connect_block[] =
79  {3,0,0,22,0x11,0xE0,0x00,0x00,0x00,0x01,0x00,0xC1,2,1 ,0 ,0xC2,2,1 ,3 ,0xC0,1,9};
80  static const unsigned char s7_1200_connect_block[] =
81  {3,0,0,22,0x11,0xE0,0x00,0x00,0x00,0x01,0x00,0xC1,2,1 ,0 ,0xC2,2,1 ,0 ,0xC0,1,9};
82  static const unsigned char logo_connect_block[] =
83  {3,0,0,22,0x11,0xE0,0x00,0x00,0x00,0x01,0x00, 0xC0,1,9, 0xC1,2,2,0, 0xC2,2,2,0};
84  //{3,0,0,22,0x11,0xE0,0x00,0x00,0x00,0x01,0x00,0xC1,2,2, 0 ,0xC2,2,2 ,0 ,0xC0,1,9}; // this should be equivalent to the above (see detailed description)
85  static const unsigned char other_connect_block[] =
86  {3,0,0,22,0x11,0xE0,0x00,0x00,0x00,0x01,0x00,0xC1,2,1 ,0 ,0xC2,2,0 ,1 ,0xC0,1,9};
87  //######### Description of the individual bytes within the connect_block (connect request) ###
88  //{3,0,0,22,0x11,0xE0,0x00,0x00,0x00,0x01,0x00,0xC1,2,1 ,0 ,0xC2,2,0 ,1 ,0xC0,1,9};
89  // | | | | | |- Identifier: Maximum TPDU size will follow, 1 byte,
90  // | | | | | where 9 means max 512 octets
91  // | | | | |---------------- Identifier: Called TSAP will follow, 2 byte,
92  // | | | | where (1=PG, 2=OP, 3=Step7Basic),
93  // | | | | rack=0 slot=1 (upper_3_bit_is_rack /
94  // | | | | lower_5_bit_is_slot)
95  // | | | |------------------------------- Identifier: Calling TSAP will follow, 2 byte,
96  // | | | where (1=PG, 2=OP) 3=Step7Basic),
97  // | | | rack=0 slot=0 (upper_3_bit_is_rack /
98  // | | | lower_5_bit_is_slot)
99  // | | |------------------------------------------------------------ 0xEO = Connection Request Code,
100  // | | destination ref high/low = 0,0
101  // | | source ref high/low = 0,1
102  // | | Class and Option = 0
103  // | |----------------------------------------------------------------- 0x11 = 17 = Number of bytes that follow
104  // |--------------------------------------------------------------------------- ISO_HEADER: version=3 reserved=0
105  // lenght_high=0 length_low=22 byte
106  //#############################################################################################
107  unsigned char connect_block[22];
108 
109  unsigned char connect_block2[] =
110  {0x03,0x00,0x00,0x19,0x02,0xF0,0x80,0x32,0x01,0x00,0x00,0xCC,0xC1,0x00,0x08,0x00,0x00,0xF0,0x00,0x00,0x01,0x00,0x01,0x03,0xC0};
111  unsigned char buf[512];
112 
113  if(use_cb)
114  {
115  memcpy(connect_block,cb,sizeof(cb));
116  }
117  else
118  {
119  if (plc_type == S7_200) memcpy(connect_block,s7_200_connect_block,sizeof(connect_block));
120  else if(plc_type == S7_300) memcpy(connect_block,s7_300_connect_block,sizeof(connect_block));
121  else if(plc_type == S7_400) memcpy(connect_block,s7_400_connect_block,sizeof(connect_block));
122  else if(plc_type == S7_1200) memcpy(connect_block,s7_1200_connect_block,sizeof(connect_block));
123  else if(plc_type == LOGO) memcpy(connect_block,logo_connect_block,sizeof(connect_block));
124  else memcpy(connect_block,other_connect_block,sizeof(connect_block));
125 
126  // according to an unproofen theory siemens chooses the TSAP as follows
127  // connect_block[17] = 2; Function (1=PG,2=OP,3=Step7Basic)
128  // connect_block[18] = upper_3_bit_is_rack / lower_5_bit_is_slot
129  // Hint: use tcpdump to figure it out (host = ip_adr of your PLC)
130  // tcpdump -A -i eth0 -t -q -s 0 "host 192.168.1.14 && port 102"
131  if(function != -1) connect_block[17] = function;
132  if(rack_slot != -1) connect_block[18] = rack_slot;
133  }
134 
135  for(i=0; i<3; i++)
136  {
137  if(rlSocket::connect() >= 0)
138  {
139  // exchange TSAP
140  rlDebugPrintf("write connect_block\n");
141  rlSocket::write(connect_block,sizeof(connect_block));
142  ret = rlSocket::read(&ih,sizeof(ih),TIMEOUT);
143  rlDebugPrintf("read ih ret=%d\n",ret);
144  if(ret <= 0) { rlSocket::disconnect(); continue; }
145  length = ih.length_high*256 + ih.length_low;
146  rlDebugPrintf("read buf length=%d\n",length);
147  ret = rlSocket::read(buf,length-sizeof(ih),TIMEOUT);
148  rlDebugPrintf("read buf ret=%d\n",ret);
149  if(ret <= 0) { rlSocket::disconnect(); continue; }
150  if(length == 22)
151  {
152  for(i2=0; i2<3; i2++)
153  {
154  rlDebugPrintf("write connect_block2\n");
155  rlSocket::write(connect_block2,sizeof(connect_block2));
156  ret = rlSocket::read(&ih,sizeof(ih),TIMEOUT);
157  rlDebugPrintf("read2 ih ret=%d\n",ret);
158  length = ih.length_high*256 + ih.length_low;
159  rlDebugPrintf("read2 buf length=%d\n",length);
160  ret = rlSocket::read(buf,length-sizeof(ih),TIMEOUT);
161  rlDebugPrintf("read2 buf ret=%d\n",ret);
162  if(ret <= 0) { rlSocket::disconnect(); continue; }
163  if(ret > 0)
164  {
165  rlDebugPrintf("connect success\n");
166  return;
167  }
168  }
170  return;
171  }
172  }
173  else
174  {
175  rlsleep(100);
176  rlDebugPrintf("connect failed\n");
177  }
178  }
179 }
180 
182 {
183  int ret;
184  switch(org)
185  {
186  /* before suggestions from sps-forum.de
187  case ORG_DB: ret = 0x84; break; //[10] Datenbaustein
188  case ORG_M: ret = 0x83; break; //[10] Merker
189  case ORG_E: ret = 0x81; break; //[10] Eingang
190  case ORG_A: ret = 0x82; break; //[10] Ausgang
191  case ORG_PEPA: ret = 0x80; break; //[10] Peripheral Area R/W [tested by VSA]
192  case ORG_Z: ret = 0x84; break; //[10] not tested
193  case ORG_T: ret = 29; break; //[10] Timer
194  default: return 0x83; break;
195  */
196  case ORG_DB: ret = 0x84; break; //[10] Datenbaustein
197  case ORG_M: ret = 0x83; break; //[10] Merker
198  case ORG_E: ret = 0x81; break; //[10] Eingang
199  case ORG_A: ret = 0x82; break; //[10] Ausgang
200  case ORG_PEPA: ret = 0x80; break; //[10] Peripheral Area R/W [tested by VSA]
201  case ORG_Z: ret = 28; //[10] Zaehler // according sps-forum.de ---
202  if(plc_type==S7_200) ret = 30; // according sps-forum.de ...
203  break;
204  case ORG_T: ret = 29; //[10] Timer
205  if(plc_type==S7_200) ret = 31; // according sps-forum.de ...
206  break; // J. Kühner and R. Hönle
207  // Attention: The encoding of Zaehler and Timer will be different on S7_200 than to other plc models
208  default: return 0x83; break;
209  }
210  return ret;
211 }
212 int rlSiemensTCP::write(int org, int dbnr, int start_adr, int len, const unsigned char *buf, int function)
213 {
214  int i,ibuf,ret,len_byte,length;
215  if(rlSocket::isConnected() == 0) doConnect();
216  if(rlSocket::isConnected() == 0) return -1;
217 
218  len_byte = len;
219  if(len_byte > (int) sizeof(pdu)) return -1;
220  //if(org == ORG_DB) len_byte *= 2;
221  //if(org == ORG_Z) len_byte *= 2;
222  //if(org == ORG_T) len_byte *= 2;
223 
224  if((plc_type == S5 || plc_type == S7_300 || plc_type == S7_400) && fetch_write == 1)
225  {
226  rlDebugPrintf("using fetch_write\n");
227  length = sizeof(ih) + sizeof(wh) + len_byte;
228  unsigned char total_buf[sizeof(ih) + sizeof(wh) + sizeof(pdu)];
229  ih.version = 3;
230  ih.reserved = 0;
231  ih.length_high = length / 256;
232  ih.length_low = length & 0x0ff;
233  wh.ident[0] = 'S';
234  wh.ident[1] = '5';
235  wh.header_len = 16;
236  wh.ident_op_code = 1;
237  wh.op_code_len = 3;
238  wh.op_code = 3;
239  wh.ident_org_block = 3;
240  wh.len_org_block = 8;
241  wh.org_block = (unsigned char) org;
242  wh.dbnr = (unsigned char) dbnr;
243  wh.start_adr[0] = (unsigned char) start_adr / 256;
244  wh.start_adr[1] = (unsigned char) start_adr & 0x0ff;;
245  wh.len[0] = (unsigned char) len / 256;
246  wh.len[1] = (unsigned char) len & 0x0ff;;
247  wh.spare1 = 0x0ff;
248  wh.spare1_len = 2;
249  memcpy(total_buf, &ih, sizeof(ih));
250  memcpy(total_buf+sizeof(ih), &wh, sizeof(wh));
251  memcpy(total_buf+sizeof(ih)+sizeof(wh), buf, len_byte);
252  ret = rlSocket::write(total_buf, sizeof(ih)+sizeof(wh)+len_byte);
253  rlDebugPrintf("write total_buf ret=%d\n",ret);
254  if(ret < 0) return ret;
255  /*
256  ret = rlSocket::write(&ih,sizeof(ih));
257  rlDebugPrintf("write ih ret=%d\n",ret);
258  if(ret < 0) return ret;
259  ret = rlSocket::write(&wh,sizeof(wh));
260  rlDebugPrintf("write wh ret=%d\n",ret);
261  if(ret < 0) return ret;
262  ret = rlSocket::write(buf,len_byte);
263  rlDebugPrintf("write buf ret=%d\n",ret);
264  if(ret < 0) return ret;
265  */
266  ret = rlSocket::read(&ih,sizeof(ih),TIMEOUT);
267  rlDebugPrintf("read ih ret=%d\n",ret);
268  if(ret <= 0) return ret;
269  ret = rlSocket::read(&wa,sizeof(wa),TIMEOUT);
270  rlDebugPrintf("read wa ret=%d\n",ret);
271  if(ret <= 0) return ret;
272  if(wa.error_block != 0) return -1;
273  }
274  else
275  {
276  rlDebugPrintf("not using fetch_write\n");
277  i = 0;
278  pdu[i++] = 0x02;
279  pdu[i++] = 0xF0;
280  pdu[i++] = 0x80;
281  pdu[i++] = 0x32;
282  pdu[i++] = 0x01;
283  pdu[i++] = 0x00;
284  pdu[i++] = 0x00;
285  pdu[i++] = 0x00;
286  pdu[i++] = 0x00;
287  pdu[i++] = 0x00;
288  // The S7 update by Aljosa Merljak was tested on S7_200 only
289  // You could set your plc_type to S7_200 also, even if you have S7_300 || S7_400
290  // But only the else part has been tested with S7_300 and S7_400 up to now
291  //if(plc_type == S7_200)
292  // Hi Ken, currently only S7_200 was tested with this. But try if this also works with S7_400
293  if(plc_type >0) // works for all known plc_type == S7_200 || plc_type == S7_300 || plc_type == S7_400)
294  {
295  ret = 0;
296  switch(function)
297  {
298  case WriteBit: ret = write_bit (i, org, dbnr, start_adr, len, buf); break;
299  case WriteByte: ret = write_byte (i, org, dbnr, start_adr, len, buf); break;
300  }
301  if(ret < 0) return ret;
302  }
303  else // will only work for WriteByte with len_byte = 4
304  {
305  pdu[i++] = 0x0E;
306  pdu[i++] = 0x00;
307  pdu[i++] = 0x08;
308  pdu[i++] = 0x05; //0 write
309  pdu[i++] = 0x01; //1
310  pdu[i++] = 0x12; //2
311  pdu[i++] = 0x0A; //3
312  pdu[i++] = 0x10; //4
313  pdu[i++] = 0x02; //5
314  pdu[i++] = len_byte / 256; //6 0x00;
315  pdu[i++] = len_byte & 0x0ff; //7 0x04;
316  pdu[i++] = dbnr / 256; //8 0x00;
317  pdu[i++] = dbnr & 0x0ff; //9 0x00;
318  pdu[i++] = getOrg(org); //10
319  pdu[i++] = ((start_adr*8)/0x010000) & 0x0ff; //0x00; // [11] start adr/bits
320  pdu[i++] = ((start_adr*8)/0x0100) & 0x0ff; //0x00; // [12] start adr/bits
321  pdu[i++] = (start_adr*8) & 0x0ff; //0x00; // [13] start adr/bits
322  pdu[i++] = 0x00;
323  pdu[i++] = 0x04;
324  pdu[i++] = 0x00;
325  pdu[i++] = 0x20;
326  for(ibuf=0; ibuf<len_byte; ibuf++)
327  {
328  pdu[i++] = buf[ibuf];
329  if(i > (int) sizeof(pdu)) return -1;
330  }
331  }
332  ret = write_iso(pdu,i);
333  if(ret < 0) return ret;
334  ret = read_iso(pdu);
335  if(ret < 0) return ret;
336  if(pdu[15] != 0x05) return -1;
337  if(pdu[16] != 0x01) return -1;
338 
339  // CODE from Víctor Centelles
340  if(pdu[17] != 0xff)
341  {
342  if(pdu[17] == 0x0a){
343  fprintf( stderr, " > Error: Trying to access a DB that does not exist\n");
344  fprintf( stderr, "          Please, check that DB is set.   (error code: 10 (0x0a))\n");
345  return -(pdu[17]);
346  }
347  else if(pdu[17] == 0x05){
348  fprintf(stderr, " > Error: Trying to access an address that does not exist.\n");
349  fprintf(stderr, "          Please, check the address range. (error code: 5 (0x05))\n");
350  return -(pdu[17]);
351  }
352  else if(pdu[17] == 0x07){
353  fprintf(stderr, " > Error: the write data size doesn't fit item size\n"); // NO TESTED!!!
354  fprintf(stderr, "          Please, check the data size.     (error code: 7 (0x07))\n");
355  return -(pdu[17]);
356  }
357  else{
358  fprintf(stderr, " > Error: unknown error  (código %x!=0xff)\n", pdu[17]);
359  return -(pdu[17]);
360  }
361  }
362  }
363 
364  return len_byte;
365 }
366 
367 int rlSiemensTCP::write_bit(int& i, int org, int dbnr, int start_adr, int len, const unsigned char *buf)
368 {
369  int j;
370  pdu[i++] = 14 + 12 * (len - 1);
371  pdu[i++] = 0x00;
372  pdu[i++] = 6 * len - 1;
373  pdu[i++] = 0x05;
374  pdu[i++] = len;
375  for(j=0; j<len; j++)
376  {
377  pdu[i++] = 0x12;
378  pdu[i++] = 0x0a;
379  pdu[i++] = 0x10;
380  pdu[i++] = 0x01;
381  pdu[i++] = len / 256; //6 0x00;
382  pdu[i++] = 0x01; //7 number of bytes in group
383  pdu[i++] = dbnr / 256; //8 0x00;
384  pdu[i++] = dbnr & 0x0ff; //9 0x00;
385  pdu[i++] = getOrg(org); //10
386  pdu[i++] = ((start_adr / 8)/0x010000) & 0x0ff;
387  pdu[i++] = (start_adr / 0x0100) & 0x0ff; //0x00; // [12] start adr/bits
388  pdu[i++] = (start_adr + j) & 0x0ff; //0x00; // [13] start adr/bits
389  }
390  for(j=0; j<len; j++)
391  {
392  pdu[i++] = 0x00;
393  pdu[i++] = 0x03;
394  pdu[i++] = 0x00;
395  pdu[i++] = 0x01;
396  pdu[i++] = (buf[j]>0) ? 0x01 : 0x00;
397  if(j < len - 1 ) pdu[i++] = 0x00;
398  if(i > (int) sizeof(pdu)) return -1;
399  }
400  return i;
401 }
402 
403 int rlSiemensTCP::write_byte(int& i, int org, int dbnr, int start_adr, int len, const unsigned char *buf)
404 {
405  pdu[i++] = 0x0e;
406  pdu[i++] = 0x00;
407  pdu[i++] = 5 + len - 1;
408  pdu[i++] = 0x05;
409  pdu[i++] = 0x01;
410  pdu[i++] = 0x12;
411  pdu[i++] = 0x0a;
412  pdu[i++] = 0x10;
413  pdu[i++] = 0x02;
414  pdu[i++] = len / 256; //6 0x00;
415  pdu[i++] = len & 0x0ff; //7 number of bytes
416  pdu[i++] = dbnr / 256; //8 0x00;
417  pdu[i++] = dbnr & 0x0ff; //9 0x00;
418  pdu[i++] = getOrg(org); //10
419  pdu[i++] = start_adr /0x10000 & 0x0ff;
420  pdu[i++] = ((start_adr*8)/0x0100) & 0x0ff; //0x00; // [12] start adr/bits
421  pdu[i++] = (start_adr*8) & 0x0ff; //0x00; // [13] start adr/bits
422  pdu[i++] = 0x00;
423  pdu[i++] = 0x04;
424  pdu[i++] = (len * 8) / 256;
425  pdu[i++] = (len * 8) & 0xff;
426  for(int ibuf=0; ibuf<len; ibuf++)
427  {
428  pdu[i++] = buf[ibuf];
429  if(i > (int) sizeof(pdu)) return -1;
430  }
431  return i;
432 }
433 
434 int rlSiemensTCP::fetch(int org, int dbnr, int start_adr, int len, unsigned char *buf)
435 {
436  int i,ret,len_byte,length;
437 
438  if(rlSocket::isConnected() == 0) doConnect();
439  if(rlSocket::isConnected() == 0) return -1;
440 
441  len_byte = len;
442  //if(org == ORG_DB) len_byte *= 2;
443  //if(org == ORG_Z) len_byte *= 2;
444  //if(org == ORG_T) len_byte *= 2;
445 
446  if((plc_type == S5 || plc_type == S7_300 || plc_type == S7_400) && fetch_write == 1)
447  {
448  length = sizeof(ih) + sizeof(fh);
449  ih.version = 3;
450  ih.reserved = 0;
451  ih.length_high = length / 256;
452  ih.length_low = length & 0x0ff;
453  fh.ident[0] = 'S';
454  fh.ident[1] = '5';
455  fh.header_len = 16;
456  fh.ident_op_code = 1;
457  fh.op_code_len = 3;
458  fh.op_code = 5;
459  fh.ident_org_block = 3;
460  fh.len_org_block = 8;
461  fh.org_block = (unsigned char) org;
462  fh.dbnr = (unsigned char) dbnr;
463  fh.start_adr[0] = (unsigned char) start_adr / 256;
464  fh.start_adr[1] = (unsigned char) start_adr & 0x0ff;;
465  fh.len[0] = (unsigned char) len / 256;
466  fh.len[1] = (unsigned char) len & 0x0ff;;
467  fh.spare1 = 0x0ff;
468  fh.spare1_len = 2;
469  unsigned char total_buf[sizeof(ih)+sizeof(fh)];
470  memcpy(total_buf, &ih, sizeof(ih));
471  memcpy(total_buf+sizeof(ih), &fh, sizeof(fh));
472  ret = rlSocket::write(total_buf, sizeof(ih)+sizeof(fh));
473  rlDebugPrintf("fetch write ih ret=%d\n",ret);
474  if(ret < 0) return ret;
475  /*
476  ret = rlSocket::write(&ih,sizeof(ih));
477  rlDebugPrintf("fetch write ih ret=%d\n",ret);
478  if(ret < 0) return ret;
479  ret = rlSocket::write(&fh,sizeof(fh));
480  rlDebugPrintf("fetch write fh ret=%d\n",ret);
481  if(ret < 0) return ret;
482  */
483  ret = rlSocket::read(&ih,sizeof(ih),TIMEOUT);
484  rlDebugPrintf("fetch read ih ret=%d\n",ret);
485  if(ret <= 0) return ret;
486  ret = rlSocket::read(&fa,sizeof(fa),TIMEOUT);
487  rlDebugPrintf("fetch read fa ret=%d\n",ret);
488  if(ret <= 0) return ret;
489  if(fa.error_block != 0) return -1;
490  ret = rlSocket::read(buf,len_byte,TIMEOUT);
491  rlDebugPrintf("fetch read buf ret=%d\n",ret);
492  if(ret <= 0) return ret;
493  }
494  else
495  {
496  rlDebugPrintf("fetch:starting org=%d dbnr=%d start_adr=%d len=%d\n", org, dbnr, start_adr, len);
497  i = 0;
498  pdu[i++] = 0x02; // [0]
499  pdu[i++] = 0xF0; // [0]
500  pdu[i++] = 0x80; // [0]
501  pdu[i++] = 0x32; // [0]
502  pdu[i++] = 0x01; // [0]
503  pdu[i++] = 0x00; // [0]
504  pdu[i++] = 0x00; // [0]
505  pdu[i++] = 0x00; // [0]
506  pdu[i++] = 0x00; // [0]
507  pdu[i++] = 0x00; // [0]
508  pdu[i++] = 0x0E; // [0]
509  pdu[i++] = 0x00; // [0]
510  pdu[i++] = 0x00; // [0]
511  pdu[i++] = 0x04; // [0] read
512  pdu[i++] = 0x01; // [1]
513  pdu[i++] = 0x12; // [2]
514  pdu[i++] = 0x0A; // [3]
515  pdu[i++] = 0x10; // [4]
516  pdu[i++] = 0x02; // [5]
517  pdu[i++] = len_byte / 256; //0x00; // [6] len/bytes
518  pdu[i++] = len_byte & 0x0ff; //0x40; // [7] len/bytes
519  pdu[i++] = dbnr / 256; //0x00; // [8] dbnum
520  pdu[i++] = dbnr & 0x0ff; //0x01; // [9] dbnum
521  pdu[i++] = getOrg(org); //10
522  pdu[i] = ((start_adr*8)/0x010000) & 0x0ff; //0x00; // [11] start adr/bits
523  if (plc_type == S7_200) pdu[i] = start_adr / 0x10000;
524  i++;
525  pdu[i++] = ((start_adr*8)/0x0100) & 0x0ff; //0x00; // [12] start adr/bits
526  pdu[i++] = (start_adr*8) & 0x0ff; //0x00; // [13] start adr/bits
527  ret = write_iso(pdu,i);
528  if(ret < 0)
529  {
530  rlDebugPrintf("fetch:write_iso error ret==%d -> return -1\n", ret);
531  return ret;
532  }
533  ret = read_iso(pdu);
534  if(ret < 0)
535  {
536  rlDebugPrintf("fetch:read_iso error ret==%d -> return -1\n", ret);
537  return ret;
538  }
539  if(pdu[15] != 0x04)
540  {
541  rlDebugPrintf("fetch:pdu[15]=%d is not equal 0x04-> return -1\n", pdu[15]);
542  return -1;
543  }
544  if(pdu[16] != 0x01)
545  {
546  rlDebugPrintf("fetch:pdu[16]=%d is not equal 0x04-> return -1\n", pdu[16]);
547  return -1;
548  }
549  i = 21;
550  if(ret < i+len_byte) return -1;
551  for(int ibuf = 0; ibuf < len_byte; ibuf++)
552  {
553  buf[ibuf] = pdu[i++];
554  }
555  }
556  rlDebugPrintf("fetch:success len_byte=%d\n", len_byte);
557 
558  return len_byte;
559 }
560 
561 int rlSiemensTCP::read_iso(unsigned char *buf)
562 {
563  int i,ret,len;
564 
565  ret = rlSocket::read(&ih,sizeof(ih),TIMEOUT);
566  if(ret < 0)
567  {
568  rlDebugPrintf("read_iso:failure to read iso header ret=%d -> disconnecting\n", ret);
570  return ret;
571  }
572  if(ih.version != 3)
573  {
574  rlDebugPrintf("read_iso:header vesion mismatch version==%d -> disconnecting\n", ret);
576  return -1;
577  }
578  len = ih.length_high*256 + ih.length_low - 4;
579  if(len <= 0)
580  {
581  rlDebugPrintf("read_iso:len==%d from iso header is negative -> disconnecting\n", len);
583  return -1;
584  }
585  if(len > (int) sizeof(pdu))
586  {
587  rlDebugPrintf("read_iso:len==%d from iso header is larger than max PDU size -> disconnecting\n", len);
589  return -1;
590  }
591  ret = rlSocket::read(buf,len,TIMEOUT);
592  if(ret < 0)
593  {
594  rlDebugPrintf("read_iso:read buf got timeout -> disconnecting\n");
596  return ret;
597  }
598  if(rlDebugPrintfState != 0)
599  {
600  ::printf("read_iso() len=%d\n", len);
601  for(i=0; i<len; i++) ::printf("%02x,",buf[i]);
602  ::printf("\n");
603  }
604  return len;
605 }
606 
607 int rlSiemensTCP::write_iso(unsigned char *buf, int len)
608 {
609  int i,ret;
610 
611  if(len > (int) sizeof(pdu)) return -1;
612  if(rlSocket::isConnected() == 0) doConnect();
613  if(rlSocket::isConnected() == 0) return -1;
614 
615  // speedup siemens communication as suggested by Vincent Segui Pascual
616  // do only 1 write
617  unsigned char total_buf[sizeof(ih)+sizeof(pdu)];
618  ih.version = 3;
619  ih.reserved = 0;
620  ih.length_high = (len+4) / 256;
621  ih.length_low = (len+4) & 0x0ff;
622  memcpy(total_buf, &ih, sizeof(ih));
623  memcpy(total_buf + sizeof(ih), buf, sizeof(ih)+len);
624  ret = rlSocket::write(total_buf, sizeof(ih)+len);
625  if(ret < 0)
626  {
627  rlDebugPrintf("write_iso:failure to write buf -> disconnecting\n");
629  return ret;
630  }
631 /*
632  ih.version = 3;
633  ih.reserved = 0;
634  ih.length_high = (len+4) / 256;
635  ih.length_low = (len+4) & 0x0ff;
636  ret = rlSocket::write(&ih,sizeof(ih));
637  if(ret < 0)
638  {
639  rlDebugPrintf("write_iso:failure to write iso header -> disconnecting\n");
640  rlSocket::disconnect();
641  return ret;
642  }
643  ret = rlSocket::write(buf,len);
644  if(ret < 0)
645  {
646  rlDebugPrintf("write_iso:failure to write buf -> disconnecting\n");
647  rlSocket::disconnect();
648  return ret;
649  }
650 */
651  if(rlDebugPrintfState != 0)
652  {
653  ::printf("write_iso() len=%d\n", len);
654  for(i=0; i<len; i++) ::printf("%02x,",buf[i]);
655  ::printf("\n");
656  }
657  return len;
658 }
int rlDebugPrintf(const char *format,...)
Definition: rlcutil.cpp:61
unsigned char spare1_len
Definition: rlsiemenstcp.h:196
unsigned char error_block
Definition: rlsiemenstcp.h:207
virtual ~rlSiemensTCP()
unsigned char len_org_block
Definition: rlsiemenstcp.h:220
int write_iso(unsigned char *buf, int len)
unsigned char spare1
Definition: rlsiemenstcp.h:195
int write(const void *buf, int len)
Definition: rlsocket.cpp:292
unsigned char version
Definition: rlsiemenstcp.h:177
unsigned char ident_org_block
Definition: rlsiemenstcp.h:219
unsigned char error_block
Definition: rlsiemenstcp.h:237
unsigned char ident[2]
Definition: rlsiemenstcp.h:184
unsigned char org_block
Definition: rlsiemenstcp.h:191
unsigned char length_low
Definition: rlsiemenstcp.h:180
unsigned char op_code
Definition: rlsiemenstcp.h:188
unsigned char start_adr[2]
Definition: rlsiemenstcp.h:193
unsigned char op_code_len
Definition: rlsiemenstcp.h:187
unsigned char len_org_block
Definition: rlsiemenstcp.h:190
unsigned char ident[2]
Definition: rlsiemenstcp.h:214
unsigned char header_len
Definition: rlsiemenstcp.h:185
#define TIMEOUT
unsigned char dbnr
Definition: rlsiemenstcp.h:222
unsigned char org_block
Definition: rlsiemenstcp.h:221
int read_iso(unsigned char *buf)
int setConnectBlock(const unsigned char *connect_block)
unsigned char pdu[2048]
Definition: rlsiemenstcp.h:250
unsigned char dbnr
Definition: rlsiemenstcp.h:192
int getConnectBlock(unsigned char *connect_block)
unsigned char len[2]
Definition: rlsiemenstcp.h:224
int read(void *buf, int len, int timeout=0)
Definition: rlsocket.cpp:191
int getDefaultConnectBlock(unsigned char *connect_block)
unsigned char len[2]
Definition: rlsiemenstcp.h:194
int getOrg(int org)
unsigned char op_code
Definition: rlsiemenstcp.h:218
int write_bit(int &i, int org, int dbnr, int start_adr, int len, const unsigned char *buf)
unsigned char spare1_len
Definition: rlsiemenstcp.h:226
int fetch(int org, int dbnr, int start_adr, int length, unsigned char *buf)
void doConnect()
void rlsleep(long msec)
Definition: rlwthread.cpp:396
unsigned char ident_op_code
Definition: rlsiemenstcp.h:216
unsigned char ident_op_code
Definition: rlsiemenstcp.h:186
unsigned char reserved
Definition: rlsiemenstcp.h:178
int write_byte(int &i, int org, int dbnr, int start_adr, int length, const unsigned char *buf)
unsigned char start_adr[2]
Definition: rlsiemenstcp.h:223
int rlDebugPrintfState
Definition: rlcutil.cpp:52
int write(int org, int dbnr, int start_adr, int length, const unsigned char *buf, int function=WriteByte)
int connect()
Definition: rlsocket.cpp:321
#define ISO_PORT
int disconnect()
Definition: rlsocket.cpp:545
int isConnected()
Definition: rlsocket.cpp:559
unsigned char spare1
Definition: rlsiemenstcp.h:225
unsigned char op_code_len
Definition: rlsiemenstcp.h:217
unsigned char cb[22]
Definition: rlsiemenstcp.h:252
unsigned char header_len
Definition: rlsiemenstcp.h:215
unsigned char length_high
Definition: rlsiemenstcp.h:179
unsigned char ident_org_block
Definition: rlsiemenstcp.h:189
rlSiemensTCP(const char *adr, int _plc_type=rlSiemensTCP::ANY_SIEMENS_COMPATIBLE_PLC, int _fetch_write=1, int function=-1, int rack_slot=-1)
int printf(const char *format,...)
Definition: rlsocket.cpp:586