SVHReceiveThread.cpp
Go to the documentation of this file.
1 // this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
2 
3 // -- BEGIN LICENSE BLOCK ----------------------------------------------
4 // This file is part of the SCHUNK SVH Driver suite.
5 //
6 // This program is free software licensed under the LGPL
7 // (GNU LESSER GENERAL PUBLIC LICENSE Version 3).
8 // You can find a copy of this license in LICENSE folder in the top
9 // directory of the source code.
10 //
11 // © Copyright 2014 SCHUNK Mobile Greifsysteme GmbH, Lauffen/Neckar Germany
12 // © Copyright 2014 FZI Forschungszentrum Informatik, Karlsruhe, Germany
13 //
14 // -- END LICENSE BLOCK ------------------------------------------------
15 
16 //----------------------------------------------------------------------
29 //----------------------------------------------------------------------
31 #include <driver_svh/Logging.h>
32 
33 
34 using icl_comm::ArrayBuilder;
35 
36 namespace driver_svh {
37 
39  ReceivedPacketCallback const & received_callback)
40  : PeriodicThread("SVHReceiveThread", period),
41  m_serial_device(device),
42  m_received_state(eRS_HEADER1),
43  m_length(0),
44  m_data(0, 0),
45  m_ab(0),
46  m_packets_received(0),
47  m_skipped_bytes(0),
48  m_received_callback(received_callback)
49 {}
50 
52 {
53  while (execute())
54  {
55  if (m_serial_device)// != NULL)
56  {
57  if (m_serial_device->IsOpen())
58  {
59  // All we every want to do is receiving data :)
60  if(!receiveData())
61  {
62  waitPeriod();
63  }
64  }
65  else
66  {
67  LOGGING_WARNING_C(DriverSVH, SVHReceiveThread, "Cannot read data from serial device. It is not opened!" << endl);
68  waitPeriod();
69  }
70  }
71 
72  else
73  {
74  // Wait for the thread period so that the timing is in sync.
75  waitPeriod();
76  }
77 }
78 }
79 
81 {
82 
83  /*
84  * Each packet has to follow the defined packet structure which is ensured by the following state machine.
85  * The "Bytestream" (not realy a stream) is interpreted byte by byte. If the structure is still right the
86  * next state is entered, if a wrong byte is detected the whole packet is discarded and the SM switches to
87  * the synchronization state aggain.
88  * If the SM reaches the final state the packet will be given to the packet handler to decide what to do with
89  * its content.
90  * NOTE: All layers working with a SerialPacket (except this one) assume that the packet has a valid structure
91  * and all data fields present.
92  */
93  uint8_t data_byte;
94  int bytes = m_serial_device->Read(&data_byte, sizeof(uint8_t));
95  if (bytes < 0)
96  {
97  LOGGING_TRACE_C(DriverSVH, SVHReceiveThread, "Serial read error:" << bytes << endl );
98  return false;
99  }
100  if (bytes < 1)
101  {
102  return false;
103  }
104 
105  switch (m_received_state)
106  {
107  case eRS_HEADER1:
108  {
109  if (data_byte == PACKET_HEADER1)
110  {
112  }
113  else
114  {
115  m_skipped_bytes++;
116  }
117  break;
118  }
119  case eRS_HEADER2:
120  {
121  switch (data_byte)
122  {
123  case PACKET_HEADER2:
124  {
126  break;
127  }
128  case PACKET_HEADER1:
129  {
131  m_skipped_bytes++;
132  break;
133  }
134  default:
135  {
137  m_skipped_bytes+=2;
138  break;
139  }
140  }
141  break;
142  }
143  case eRS_INDEX:
144  {
145  // Reset Array Builder for each fresh packet
146  m_ab.reset(0);
147 
148  // Data bytes are not cenverted in endianess at this point
149  m_ab.appendWithoutConversion(data_byte);
151  break;
152  }
153  case eRS_ADDRESS:
154  {
155  //get the address
156  m_ab.appendWithoutConversion(data_byte);
158  break;
159  }
160  case eRS_LENGTH1:
161  {
162  // get payload length
163  m_ab.appendWithoutConversion(data_byte);
165  break;
166  }
167  case eRS_LENGTH2:
168  {
169  // get payload length
170  m_ab.appendWithoutConversion(data_byte);
171  m_length = m_ab.readBack<uint16_t>();
173  m_data.clear();
174  m_data.reserve(m_length);
175  break;
176  }
177  case eRS_DATA:
178  {
179  // get the payload itself
180  // Some conversion due to legacy hardware calls
181  m_data.push_back(data_byte);
182  m_ab.appendWithoutConversion(data_byte);
183  if(m_data.size()>=m_length)
184  {
186  }
187  break;
188  }
189  case eRS_CHECKSUM1:
190  {
191  m_checksum1 = data_byte;
192  m_checksum2 = 0;
194  break;
195  }
196  case eRS_CHECKSUM2:
197  {
198  m_checksum2=data_byte;
199  uint8_t checksum1=m_checksum1;
200  uint8_t checksum2=m_checksum2;
201  // probe for correct checksum
202  for (size_t i = 0; i < m_data.size(); ++i)
203  {
204  checksum1 -= m_data[i];
205  checksum2 ^= m_data[i];
206  }
207 
208  if ((checksum1 == 0) && (checksum2 == 0))
209  {
210  // start with an empty package
211  // Warning: It is imperative for correct readouts to create the received_packet with the correct length!
212  SVHSerialPacket received_packet(m_length);
213  m_ab >> received_packet;
214 
216 
217  if(m_skipped_bytes>0)LOGGING_TRACE_C(DriverSVH, SVHReceiveThread, "Skipped "<<m_skipped_bytes<<" bytes "<< endl);
218  LOGGING_TRACE_C(DriverSVH, SVHReceiveThread, "Received packet index:" << received_packet.index <<", address:"<<received_packet.address<<", size:"<<received_packet.data.size() << endl);
219  m_skipped_bytes=0;
220  // notify whoever is waiting for this
222  {
223  m_received_callback(received_packet, m_packets_received);
224  }
225 
227  }
228  else
229  {
231 
232  SVHSerialPacket received_packet(m_length);
233  m_ab >> received_packet;
234 
235  if(m_skipped_bytes>0)LOGGING_TRACE_C(DriverSVH, SVHReceiveThread, "Skipped "<<m_skipped_bytes<<" bytes: "<< endl);
236  LOGGING_TRACE_C(DriverSVH, SVHReceiveThread, "Checksum error: "<< (int)checksum1<<","<<(int)checksum2<<"!=0, skipping "<<m_length+8<<"bytes, packet index:" << received_packet.index <<", address:"<<received_packet.address<<", size:"<<received_packet.data.size() << endl);
237  m_skipped_bytes=0;
239  {
240  m_received_callback(received_packet, m_packets_received);
241  }
242  }
243  break;
244  }
245  }
246 
247  return true;
248 }
249 
250 }
std::vector< uint8_t > m_data
length of received serial data
const uint8_t PACKET_HEADER1
Header sync byte 1.
tState m_received_state
current state of the state machine
boost::function< void(const SVHSerialPacket &packet, unsigned int packet_count)> ReceivedPacketCallback
definition of boost function callback for received packages
unsigned int m_skipped_bytes
counter for skipped bytes in case no packet is detected
const uint8_t PACKET_HEADER2
Header sync byte 2.
ReceivedPacketCallback m_received_callback
function callback for received packages
bool receiveData()
state machine processing received data
virtual void run()
run method of the thread, executes the main program
#define LOGGING_WARNING_C(streamname, classname, arg)
uint16_t m_length
length of received serial data
Thread for receiving messages from the serial device.
unsigned char uint8_t
ThreadStream & endl(ThreadStream &stream)
unsigned int m_packets_received
packets counter
SVHReceiveThread(const TimeSpan &period, boost::shared_ptr< Serial > device, ReceivedPacketCallback const &received_callback)
SVHReceiveThread Constructs a new Receivethread.
boost::shared_ptr< Serial > m_serial_device
pointer to serial device object
uint8_t m_checksum1
Checksum of packet.
#define LOGGING_TRACE_C(streamname, classname, arg)
unsigned short uint16_t
icl_comm::ArrayBuilder m_ab
pointer to array builder object for packet receive
The SerialPacket holds the (non generated) header and data of one message to the SVH-Hardware.


schunk_svh_driver
Author(s): Georg Heppner
autogenerated on Mon Jun 10 2019 15:04:59