Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
SerialPortIO.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5 Multimediale Systeme der Informationsverarbeitung
6 Institut fuer Informatik
7 Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 /*
26  * SerialPortIO.cpp
27  *
28  * Created on: Nov 23, 2010
29  * Author: ischiller
30  *
31  * see http://www.easysw.com/~mike/serial/serial.html for help on serial port with POSIX termios
32  * and
33  * http://www.robbayer.com/files/serial-win.pdf
34  * or
35  * http://www.codeproject.com/KB/system/serial_com.aspx for help on serial port with Windows
36  */
37 
38 #include <iostream>
39 #include "SerialPortIO.hh"
40 #include <Base/Debug/Error.hh>
41 #include <Base/Common/W32Compat.hh>
42 
43 using namespace BIAS;
44 using namespace std;
45 
47  verbose_ = verbose;
48  serialFD_ =0;
49  bIsOpen_=false;
50 }
51 
53 
54 }
55 
56 
57 bool SerialPortIO::
58 OpenPort(std::string port)
59 {
60 
61 #ifdef WIN32
62  serialFD_ = CreateFile(port.c_str(),
63  GENERIC_READ | GENERIC_WRITE,
64  0,
65  0,
66  OPEN_EXISTING,
67  FILE_ATTRIBUTE_NORMAL,
68  0);
69 
70  if(serialFD_==INVALID_HANDLE_VALUE){
71  if(GetLastError()==ERROR_FILE_NOT_FOUND){
72  if (verbose_) BIASERR("Port:"<<port<<" does not exist.");
73  return false;
74  }
75  if (verbose_) BIASERR("Could not open port:"<<port);
76  return false;
77  }
78  cout<<"Created port!"<<endl;
79  bIsOpen_ = true;
80 
81 #else ///LINUX
82  serialFD_ = open(port.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
83  if (serialFD_ == -1)
84  {
85  if (verbose_) BIASERR("Could not open port:"<<port);
86  return false;
87  }
88  else{
89  cout<<"Created port!"<<endl;
90  fcntl(serialFD_, F_SETFL, 0);
91  bIsOpen_ = true;
92  }
93 #endif
94 
95  return SetOptions();
96 }
97 
98 bool SerialPortIO::
100  if(!bIsOpen_){
101  if (verbose_) BIASERR("Serial port was not opened!");
102  return false;
103  }
104 #ifdef WIN32
105  CloseHandle(serialFD_);
106 #else
107  close(serialFD_);
108 #endif
109  return true;
110 }
111 
112 bool SerialPortIO::
113 SetOptions(unsigned baudrate,SerialPortParityMode parity,
114  bool hardwareFlowControl, bool canonicalInput,
115  bool softwareFlowControl, int stopbits ){
116  if(!bIsOpen_){
117  if (verbose_) BIASERR("Serial port was not opened!");
118  return false;
119  }
120 #ifdef WIN32
121  DCB dcbSerialParams = {0};
122  dcbSerialParams.DCBlength=sizeof(dcbSerialParams);
123  if (!GetCommState(serialFD_, &dcbSerialParams)) {
124  if (verbose_) BIASERR("Error getting com port state!");
125  return false;
126  }
127  switch(baudrate){
128  case 110:
129  dcbSerialParams.BaudRate=CBR_110;
130  break;
131  case 300:
132  dcbSerialParams.BaudRate=CBR_300;
133  break;
134  case 600:
135  dcbSerialParams.BaudRate=CBR_600;
136  break;
137  case 1200:
138  dcbSerialParams.BaudRate=CBR_1200;
139  break;
140  case 2400:
141  dcbSerialParams.BaudRate=CBR_2400;
142  break;
143  case 4800:
144  dcbSerialParams.BaudRate=CBR_4800;
145  break;
146  case 9600:
147  dcbSerialParams.BaudRate=CBR_9600;
148  break;
149  case 19200:
150  dcbSerialParams.BaudRate=CBR_19200;
151  break;
152  case 38400:
153  dcbSerialParams.BaudRate=CBR_38400;
154  break;
155  case 57600:
156  dcbSerialParams.BaudRate=CBR_57600;
157  break;
158  default:
159  BIASWARN("Not a valid Baudrate, setting to 9600 instead");
160  dcbSerialParams.BaudRate=CBR_9600;
161  break;
162  }
163  //bytesize
164  dcbSerialParams.ByteSize=8;
165  //stopbit
166  dcbSerialParams.StopBits=ONESTOPBIT;
167  //parity
168  switch(parity){
169  case SPPM_SpaceParity:
170  case SPPM_NoParity:
171  dcbSerialParams.Parity=NOPARITY;
172  break;
173  case SPPM_EvenParity:
174  dcbSerialParams.Parity=EVENPARITY;
175  break;
176  case SPPM_OddParity:
177  dcbSerialParams.Parity=ODDPARITY;
178  break;
179  default:
180  BIASERR("Invalid partity value!");
181  return false;
182  break;
183  }
184 
185  if(!SetCommState(serialFD_, &dcbSerialParams)){
186  BIASERR("Error setting com port state!");
187  }
188 #else
189  struct termios options;
190  /* Get the current options for the port...*/
191  tcgetattr(serialFD_, &options);
192  /* Set the baud rates to ... */
193  switch(baudrate){
194  case 0:
195  cfsetispeed(&options, B0);
196  cfsetospeed(&options, B0);
197  break;
198  case 50:
199  cfsetispeed(&options, B50);
200  cfsetospeed(&options, B50);
201  break;
202  case 75:
203  cfsetispeed(&options, B75);
204  cfsetospeed(&options, B75);
205  break;
206  case 110:
207  cfsetispeed(&options, B110);
208  cfsetospeed(&options, B110);
209  break;
210  case 134:
211  cfsetispeed(&options, B134);
212  cfsetospeed(&options, B134);
213  break;
214  case 150:
215  cfsetispeed(&options, B150);
216  cfsetospeed(&options, B150);
217  break;
218  case 200:
219  cfsetispeed(&options, B200);
220  cfsetospeed(&options, B200);
221  break;
222  case 300:
223  cfsetispeed(&options, B300);
224  cfsetospeed(&options, B300);
225  break;
226  case 600:
227  cfsetispeed(&options, B600);
228  cfsetospeed(&options, B600);
229  break;
230  case 1200:
231  cfsetispeed(&options, B1200);
232  cfsetospeed(&options, B1200);
233  break;
234  case 1800:
235  cfsetispeed(&options, B1800);
236  cfsetospeed(&options, B1800);
237  break;
238  case 2400:
239  cfsetispeed(&options, B2400);
240  cfsetospeed(&options, B2400);
241  break;
242  case 4800:
243  cfsetispeed(&options, B4800);
244  cfsetospeed(&options, B4800);
245  break;
246  case 9600:
247  cfsetispeed(&options, B9600);
248  cfsetospeed(&options, B9600);
249  break;
250  case 19200:
251  cfsetispeed(&options, B19200);
252  cfsetospeed(&options, B19200);
253  break;
254  case 38400:
255  cfsetispeed(&options, B38400);
256  cfsetospeed(&options, B38400);
257  break;
258  case 57600:
259  cfsetispeed(&options, B57600);
260  cfsetospeed(&options, B57600);
261  break;
262  default:
263  BIASWARN("Not a valid Baudrate, setting to 9600 instead");
264  cfsetispeed(&options, B9600);
265  cfsetospeed(&options, B9600);
266  break;
267  }
268 
269  /*Enable the receiver and set local mode...*/
270  options.c_cflag |= (CLOCAL | CREAD);
271 
272  /* set parity */
273  switch(parity){
274  case SPPM_NoParity:
275  case SPPM_SpaceParity:
276  options.c_cflag &= ~PARENB;
277  options.c_cflag &= ~CSIZE;
278  options.c_cflag |= CS8;
279  break;
280  case SPPM_EvenParity:
281  options.c_cflag |= PARENB;
282  options.c_cflag &= ~PARODD;
283  options.c_cflag &= ~CSIZE;
284  options.c_cflag |= CS7;
285  break;
286  case SPPM_OddParity:
287  options.c_cflag |= PARENB;
288  options.c_cflag |= PARODD;
289  options.c_cflag &= ~CSIZE;
290  options.c_cflag |= CS7;
291  break;
292  default:
293  BIASERR("Invalid partity value!");
294  return false;
295  break;
296  }
297 
298  switch(stopbits){
299  case 1:
300  default:
301  options.c_cflag &= ~CSTOPB;
302  case 2:
303  options.c_cflag |= CSTOPB;
304  }
305 
306  // no parity
307  options.c_iflag &= ~(INPCK | ISTRIP);
308  options.c_oflag &= ~OPOST; // raw output
309 
310  /* set hardware flow control */
311  if(hardwareFlowControl)
312  options.c_cflag |= CRTSCTS;
313  else
314  options.c_cflag &= ~CRTSCTS;
315 
316  /* set Canonical input (line oriented) */
317  if(canonicalInput)
318  options.c_lflag |= (ICANON | ECHO | ECHOE);
319  else
320  options.c_lflag &= ~(ICANON | ECHO | ECHOE |ISIG);
321 
322  /* set software Flow control */
323  if(softwareFlowControl)
324  options.c_iflag |= (IXON | IXOFF | IXANY);
325  else
326  options.c_iflag &= ~(IXON | IXOFF | IXANY);
327 
328  options.c_cc[VMIN]=0;
329  options.c_cc[VTIME]=3; //tenths of seconds
330 
331  /* Set the new options for the port...*/
332  tcsetattr(serialFD_, TCSANOW, &options);
333  tcflush(serialFD_,TCIFLUSH);
334 #endif
335 
336  return true;
337 }
338 
339 
340 /**
341 
342  */
343 bool SerialPortIO::
344 SetTimeOuts(int ReadIntervalTimeout,
345  int ReadTotalTimeoutMultiplier,int ReadTotalTimeoutConstant,
346  int WriteTotalTimeoutMultiplier,int WriteTotalTimeoutConstant){
347 #ifdef WIN32
348  COMMTIMEOUTS timeouts;
349  timeouts.ReadIntervalTimeout = ReadIntervalTimeout;
350  timeouts.ReadTotalTimeoutMultiplier = ReadTotalTimeoutMultiplier;
351  timeouts.ReadTotalTimeoutConstant = ReadTotalTimeoutConstant;
352  timeouts.WriteTotalTimeoutMultiplier = WriteTotalTimeoutMultiplier;
353  timeouts.WriteTotalTimeoutConstant = WriteTotalTimeoutConstant;
354  if (!SetCommTimeouts(serialFD_, &timeouts)) // Error setting time-outs.
355  {
356  BIASERR("Error setting com port state!");
357  return false;
358  }
359 #else
360  struct termios options;
361  /* Get the current options for the port...*/
362  tcgetattr(serialFD_, &options);
363  options.c_cc[VMIN]=0;
364  options.c_cc[VTIME]=ReadIntervalTimeout;
365  /* Set the new options for the port...*/
366  int ret = tcsetattr(serialFD_, TCSANOW, &options);
367  if(ret<0)
368  {
369  BIASERR("Error setting com port state!");
370  return false;
371  }
372  tcflush(serialFD_,TCIFLUSH);
373 #endif
374  return true;
375 }
376 
377 bool SerialPortIO::
378 ReadString(std::string& message, bool waitForMessage){
379  if(!bIsOpen_){
380  BIASERR("Serial port was not opened!");
381  return false;
382  }
383 
384  const int length = 255;
385  char buffer[length+1]={0}; /* Input buffer */
386 #ifdef WIN32
387 // COMMTIMEOUTS timeouts;
388 // if(waitForMessage){
389 // timeouts.ReadIntervalTimeout=5000;
390 // timeouts.ReadTotalTimeoutConstant=50;
391 // timeouts.ReadTotalTimeoutMultiplier=10;
392 // }
393 // else{
394 // timeouts.ReadIntervalTimeout=50;
395 // timeouts.ReadTotalTimeoutConstant=50;
396 // timeouts.ReadTotalTimeoutMultiplier=10;
397 // }
398 // if(!SetCommTimeouts(serialFD_, &timeouts)){
399 // BIASWARN("Error setting timeouts to port!");
400 // }
401 
402  DWORD dwBytesRead = 0;
403  if(!ReadFile(serialFD_, buffer, length, &dwBytesRead, NULL)){
404  BIASERR("Error reading from serial port!");
405  return false;
406  }
407 
408 #else
409 
410 // if(waitForMessage)
411 // fcntl(serialFD_, F_SETFL, 0);
412 // else
413 // fcntl(serialFD_, F_SETFL, FNDELAY);
414 
415  //read
416  char *bufptr; /* Current char in buffer */
417  int nbytes; /* Number of bytes read */
418  bufptr = buffer;
419 
420  while ((nbytes = read(serialFD_, bufptr, buffer + sizeof(buffer) - bufptr - 1)) > 0)
421  {
422  bufptr += nbytes;
423  if (bufptr[-1] == '\n' || bufptr[-1] == '\r')
424  break;
425  }
426 #endif
427 
428  message = buffer;
429  return true;
430 }
431 
432 int SerialPortIO::
433 ReadBytes(unsigned char* message,int nrBytes,bool waitForMessage){
434  if(!bIsOpen_){
435  BIASERR("Serial port was not opened!")
436  return false;
437  }
438 
439 #ifdef WIN32
440  COMMTIMEOUTS timeouts={0};
441  if(waitForMessage){
442  timeouts.ReadIntervalTimeout=5000;
443  timeouts.ReadTotalTimeoutConstant=50;
444  timeouts.ReadTotalTimeoutMultiplier=10;
445  }
446  else{
447  timeouts.ReadIntervalTimeout=50;
448  timeouts.ReadTotalTimeoutConstant=50;
449  timeouts.ReadTotalTimeoutMultiplier=10;
450  }
451  if(!SetCommTimeouts(serialFD_, &timeouts)){
452  BIASWARN("Error setting timeouts to port!");
453  }
454 
455  DWORD dwBytesRead = 0;
456  if(!ReadFile(serialFD_, message, nrBytes, &dwBytesRead, NULL)){
457  BIASERR("Error reading from serial port!");
458  return 0;
459  }
460  else
461  return (int)dwBytesRead;
462 #else
463 
464  if(waitForMessage)
465  fcntl(serialFD_, F_SETFL, 0);
466  else
467  fcntl(serialFD_, F_SETFL, FNDELAY);
468 
469  //read
470  int nbytes=0; /* Number of bytes read */
471  nbytes = read(serialFD_, message, nrBytes);
472  return nbytes;
473 #endif
474 }
475 
476 bool SerialPortIO::
477 WriteString(std::string message){
478  int attempts = 10;
479  if(!bIsOpen_){
480  BIASERR("Serial port was not opened!")
481  return false;
482  }
483 #ifdef WIN32
484  DWORD dwBytesWritten = 0;
485  if(!WriteFile(serialFD_, message.c_str(), message.size(), &dwBytesWritten, NULL)){
486  BIASERR("Error writing to serial port!");
487  return false;
488  }
489 #else
490  int n = 0;
491  for(int i=0;i<attempts;i++){
492  n = write(serialFD_, message.c_str(), message.size());
493  if(n > 0) continue;
494  biasusleep(500);
495  }
496  if (n < 0){
497  BIASERR("Error writing to serial port!");
498  return false;
499  }
500 #endif
501  return true;
502 }
503 
504 /* returns TRUE if all is OK */
505 bool SerialPortIO::
506 WriteBytes(unsigned char *message, int nrBytes)
507 {
508  int attempts = 10;
509 #ifdef WIN32
510  DWORD dwBytesWritten = 0;
511  if(!WriteFile(serialFD_, message, nrBytes, &dwBytesWritten, NULL)){
512  BIASERR("Error writing to serial port!");
513  return false;
514  }
515 #else
516  int n = 0;
517  for(int i=0;i<attempts;i++){
518  n = write(serialFD_, message, nrBytes);
519  if(n > 0) continue;
520  biasusleep(500);
521  }
522  if (n < 0){
523  BIASERR("Error writing to serial port!");
524  return false;
525  }
526 #ifdef BIAS_DEBUG
527  cout<<"Wrote:"<<n<<" bytes.\n";
528 #endif
529 #endif
530  return true;
531 }
532 
533 bool SerialPortIO::
534 GetPetScanRFIDFromString(std::string message, std::string& rfid){
535 
536  int length = message.length();
537  //std::cout<<"Length:"<<length<<std::endl;
538  if(length>=31){
539  std::string start = message.substr(0,4);
540  std::string chiptype = message.substr(5,4);
541  std::string id = message.substr(9,16);
542  std::string separator = message.substr(25,1);
543  std::string control = message.substr(26,4);
544  // std::cout<<"Start:"<<start<<" chiptype:"<<chiptype<<" id:"<<id<<" separator:"
545  // <<separator<<" control:"<<control<<std::endl;
546  rfid = id;
547 
548  //check checksum
549  // unsigned int crc_checksum=0xffff;
550  // unsigned int crc_poly = 0x1021;
551  // unsigned char ch=' ';
552  // char i=' ',xor_flag=' ';
553  // unsigned char *inbuffer = (unsigned char *)message.c_str();
554  // while(*inbuffer!=0){
555  // ch=*inbuffer++;
556  // for(i=0;i<8;i++){
557  // xor_flag = (crc_checksum & 0x8000)?1:0;
558  // crc_checksum = crc_checksum<<1;
559  // if(ch & 0x80) crc_checksum++;
560  // if(xor_flag) crc_checksum = crc_checksum ^crc_poly;
561  // ch = ch<<1;
562  // }
563  // }
564  // for(i=0;i<16;i++){
565  // xor_flag=(crc_checksum & 0x8000)?1:0;
566  // crc_checksum = crc_checksum<<1;
567  // if(xor_flag) crc_checksum = crc_checksum ^ crc_poly;
568  // }
569  //
570  // unsigned int check = atoi(control.c_str());
571  // std::cout<<"C:"<<check<<std::endl;
572  // std::cout<<"Checksum:"<<crc_checksum<<std::endl;
573 
574  return true;
575  }
576  else{
577  rfid = "";
578  return false;
579  }
580 
581 }
bool GetPetScanRFIDFromString(std::string message, std::string &rfid)
parses values of PetScan RT100 V5 format Start Chip Value *Control U FDXB945 000000869846*FFA9 ...
int ReadBytes(unsigned char *message, int nrBytes, bool waitForMessage=true)
Read bytes from the port, port has to be open.
bool ReadString(std::string &message, bool waitForMessage=true)
Read a string from port, port has to be open.
bool ClosePort()
Close port.
bool WriteBytes(unsigned char *message, int nrBytes)
Write bytes to the port, port has to be open.
bool OpenPort(std::string port)
Open port, e.g.
SerialPortIO(bool verbose=true)
standard constructor
bool SetTimeOuts(int ReadIntervalTimeout, int ReadTotalTimeoutMultiplier, int ReadTotalTimeoutConstant, int WriteTotalTimeoutMultiplier, int WriteTotalTimeoutConstant)
in linux all exept ReadTotalTimeoutConstant is ignored
virtual ~SerialPortIO()
standard destructor
bool WriteString(std::string message)
Write a string to the port, port has to be open.
SerialPortParityMode
Definition: SerialPortIO.hh:44
bool SetOptions(unsigned baudrate=9600, SerialPortParityMode parity=SPPM_NoParity, bool hardwareFlowControl=false, bool canonicalInput=true, bool softwareFlowControl=false, int stopbits=1)
Set Options for opened port, use OpenPort before.