CoLaBProtocolHandler.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2023 SICK AG, Waldkirch
3 //
4 // SPDX-License-Identifier: Unlicense
5 
6 #include "CoLaBProtocolHandler.h"
7 
8 #include <cassert>
9 #include <cstddef> // for size_t
10 
11 #include "VisionaryEndian.h"
12 
13 namespace {
14 constexpr std::uint8_t kStx = 0x02u;
15 }
16 
17 namespace visionary {
18 
19 CoLaBProtocolHandler::CoLaBProtocolHandler(ITransport& rTransport) : m_rtransport(rTransport)
20 {
21 }
22 
24 
25 std::uint8_t CoLaBProtocolHandler::calculateChecksum(ByteBuffer::const_iterator begin,
26  ByteBuffer::const_iterator end) const
27 {
28  std::uint8_t checksum = 0;
29  for (auto it = begin; it != end; ++it)
30  {
31  checksum ^= *it;
32  }
33  return checksum;
34 }
35 
36 // parse a protocol response
38 {
39  ByteBuffer buffer;
40  buffer.reserve(64u); // typical maximum response size
41 
42  // get response
43  // check for a run of 4 STX
44  constexpr std::size_t numExpectedStx = 4u;
45  std::size_t stxRecvLeft = numExpectedStx;
46 
47  while (stxRecvLeft > 0u)
48  {
49  ITransport::send_return_t nReceived = m_rtransport.recv(buffer, stxRecvLeft);
50 
51  if (nReceived <= 0)
52  {
53  // error or stream closed
54  // return an empty buffer as indicator
55  buffer.clear();
56  return buffer;
57  }
58 
59  // check if we have only STX in a row
60  // if another byte was encountered, reset all counters so that we are looking for a new run of 4 STX
61  ByteBuffer::iterator it{buffer.begin()};
62  while (it != buffer.end())
63  {
64  if (kStx == *it)
65  {
66  --stxRecvLeft;
67  ++it;
68  }
69  else
70  {
71  buffer.erase(buffer.begin(), it);
72  stxRecvLeft = numExpectedStx;
73  it = buffer.begin();
74  }
75  }
76  }
77  buffer.clear();
78 
79  // get length
80  if (static_cast<ITransport::recv_return_t>(sizeof(std::uint32_t)) != m_rtransport.read(buffer, sizeof(std::uint32_t)))
81  {
82  // error or stream closed
83  // return an empty buffer as indicator
84  buffer.clear();
85  return buffer;
86  }
87  const std::uint32_t length = readUnalignBigEndian<std::uint32_t>(buffer.data());
88 
89  buffer.clear();
90  // read payload + 1 byte checksum
91  if (static_cast<ITransport::recv_return_t>(length + 1u) != m_rtransport.read(buffer, length + 1u))
92  {
93  // error or stream closed
94  // return an empty buffer as indicator
95  buffer.clear();
96  return buffer;
97  }
98 
99  // drop checksum
100  buffer.pop_back();
101 
102  return buffer;
103 }
104 
105 // parse a command response
107 {
108  return readProtocol();
109 }
110 
111 // build a protocol header
113  std::size_t extraReserve)
114 {
116  header.reserve(4u + 4u + extraReserve);
117 
118  // insert magic bytes
119  header.insert(header.end(), {kStx, kStx, kStx, kStx});
120 
121  // insert length
122  {
123  const std::uint32_t v = static_cast<std::uint32_t>(payloadSize);
124  std::uint8_t b[4u];
125  writeUnalignBigEndian<std::uint32_t>(b, sizeof(b), v);
126  header.insert(header.end(), b, b + 4u);
127  }
128 
129  return header;
130 }
131 
132 // build a message header
134  std::size_t extraReserve)
135 {
136  return createProtocolHeader(payloadSize, extraReserve);
137 }
138 
139 // send a command using the control session
141 {
142  const ByteBuffer& cmdBuffer{cmd.getBuffer()};
143 
144  // create buffer with command header in place (and reserve space for the cmd and the checksum byte)
145  ByteBuffer buffer{createCommandHeader(cmdBuffer.size(), cmdBuffer.size() + 1u)};
146 
147  // add cmd
148  buffer.insert(buffer.end(), cmdBuffer.begin(), cmdBuffer.end());
149 
150  // Add checksum to end
151  constexpr std::size_t checksum_offset = 4u + 4u; // after STX + length
152  buffer.insert(buffer.end(), calculateChecksum(buffer.cbegin() + checksum_offset, buffer.cend()));
153 
154  // send to socket
155  if (m_rtransport.send(buffer) != static_cast<ITransport::send_return_t>(buffer.size()))
156  {
158  }
159  buffer.clear();
160 
161  // get response
163  if (0u == response.size())
164  {
166  }
167 
168  return CoLaCommand(response);
169 }
170 
171 // open a new control session
172 bool CoLaBProtocolHandler::openSession(std::uint8_t /*sessionTimeout secs*/)
173 {
174  // we don't have a session id byte in CoLaB protocol. Nothing to do here.
175  return true;
176 }
177 
178 // close the control session
180 {
181  // we don't have a session id byte in CoLaB protocol. Nothing to do here.
182 }
183 
184 } // namespace visionary
response
const std::string response
VisionaryEndian.h
visionary::CoLaBProtocolHandler::readProtocol
ByteBuffer readProtocol()
parse a response on protocol level
Definition: CoLaBProtocolHandler.cpp:37
visionary::ITransport::read
virtual recv_return_t read(ByteBuffer &buffer, std::size_t nBytesToReceive)=0
visionary::CoLaBProtocolHandler::send
CoLaCommand send(CoLaCommand cmd) override
send cola cmd and receive cola response
Definition: CoLaBProtocolHandler.cpp:140
visionary::CoLaBProtocolHandler::ByteBuffer
std::vector< std::uint8_t > ByteBuffer
Definition: CoLaBProtocolHandler.h:30
visionary::CoLaCommand::networkErrorCommand
static CoLaCommand networkErrorCommand()
Create a command for network errors.
Definition: CoLaCommand.cpp:164
visionary::ITransport::recv_return_t
ssize_t recv_return_t
Definition: ITransport.h:29
visionary
Definition: MD5.cpp:44
visionary::CoLaCommand
Definition: CoLaCommand.h:17
visionary::CoLaBProtocolHandler::openSession
bool openSession(std::uint8_t sessionTimeout) override
Definition: CoLaBProtocolHandler.cpp:172
visionary::CoLaBProtocolHandler::createCommandHeader
ByteBuffer createCommandHeader(std::size_t payloadSize, std::size_t extraReserve=0u)
Definition: CoLaBProtocolHandler.cpp:133
visionary::CoLaBProtocolHandler::CoLaBProtocolHandler
CoLaBProtocolHandler(ITransport &rTransport)
Definition: CoLaBProtocolHandler.cpp:19
boost::foreach_detail_::begin
auto_any< BOOST_DEDUCED_TYPENAME foreach_iterator< T, C >::type > begin(auto_any_t col, type2type< T, C > *, boost::mpl::true_ *)
Definition: foreach.hpp:660
boost::foreach_detail_::end
auto_any< BOOST_DEDUCED_TYPENAME foreach_iterator< T, C >::type > end(auto_any_t col, type2type< T, C > *, boost::mpl::true_ *)
Definition: foreach.hpp:700
visionary::CoLaBProtocolHandler::createProtocolHeader
ByteBuffer createProtocolHeader(std::size_t payloadSize, std::size_t extraReserve=0u)
Definition: CoLaBProtocolHandler.cpp:112
visionary::ITransport::send_return_t
ssize_t send_return_t
Definition: ITransport.h:28
visionary::CoLaBProtocolHandler::~CoLaBProtocolHandler
~CoLaBProtocolHandler() override
visionary::CoLaBProtocolHandler::calculateChecksum
std::uint8_t calculateChecksum(ByteBuffer::const_iterator begin, ByteBuffer::const_iterator end) const
Definition: CoLaBProtocolHandler.cpp:25
visionary::CoLaBProtocolHandler::m_rtransport
ITransport & m_rtransport
Definition: CoLaBProtocolHandler.h:41
visionary::ITransport::send
send_return_t send(const std::vector< T > &buffer)
Definition: ITransport.h:45
length
TFSIMD_FORCE_INLINE tfScalar length(const Quaternion &q)
CoLaBProtocolHandler.h
visionary::CoLaBProtocolHandler::closeSession
void closeSession() override
Definition: CoLaBProtocolHandler.cpp:179
visionary::ITransport::recv
virtual recv_return_t recv(ByteBuffer &buffer, std::size_t maxBytesToReceive)=0
visionary::ITransport
Definition: ITransport.h:19
cmd
string cmd
header
const std::string header
visionary::CoLaBProtocolHandler::readResponse
ByteBuffer readResponse()
read a command response packet
Definition: CoLaBProtocolHandler.cpp:106


sick_visionary_ros
Author(s): SICK AG TechSupport 3D Snapshot
autogenerated on Thu Feb 8 2024 03:38:05