VisionaryDataStream.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 "VisionaryDataStream.h"
7 
8 #include <cstddef> // for size_t
9 #include <cstdio>
10 
11 #include <iostream>
12 
13 #include "VisionaryEndian.h"
14 
15 namespace visionary {
16 
17 VisionaryDataStream::VisionaryDataStream(std::shared_ptr<VisionaryData> dataHandler)
18  : m_dataHandler(std::move(dataHandler))
19 {
20 }
21 
23 {
24  close();
25 }
26 
27 bool VisionaryDataStream::open(const std::string& hostname, std::uint16_t port, std::uint32_t timeoutMs)
28 {
29  m_pTransport = nullptr;
30 
31  std::unique_ptr<TcpSocket> pTransport(new TcpSocket());
32 
33  if (pTransport->connect(hostname, port, timeoutMs) != 0)
34  {
35  return false;
36  }
37 
38  m_pTransport = std::move(pTransport);
39 
40  return true;
41 }
42 
43 bool VisionaryDataStream::open(std::unique_ptr<ITransport>& pTransport)
44 {
45  m_pTransport = std::move(pTransport);
46  return true;
47 }
48 
50 {
51  if (m_pTransport)
52  {
53  m_pTransport->shutdown();
54  m_pTransport = nullptr;
55  }
56 }
57 
59 {
60  std::size_t elements = 0;
61  ByteBuffer buffer;
62 
63  while (elements < 4)
64  {
65  if (m_pTransport->read(buffer, 1) < 1)
66  {
67  return false;
68  }
69  if (0x02 == buffer[0])
70  {
71  elements++;
72  }
73  else
74  {
75  elements = 0;
76  }
77  }
78 
79  return true;
80 }
81 
83 {
84  if (!syncCoLa())
85  {
86  return false;
87  }
88 
89  std::vector<std::uint8_t> buffer;
90 
91  // Read package length
92  if (m_pTransport->read(buffer, sizeof(std::uint32_t)) < static_cast<TcpSocket::recv_return_t>(sizeof(std::uint32_t)))
93  {
94  std::cout << "Received less than the required 4 package length bytes." << std::endl;
95  return false;
96  }
97 
98  const auto packageLength = readUnalignBigEndian<std::uint32_t>(buffer.data());
99 
100  if (packageLength < 3u)
101  {
102  std::cout << "Invalid package length " << packageLength << ". Should be at least 3" << std::endl;
103  return false;
104  }
105 
106  // Receive the frame data
107  std::size_t remainingBytesToReceive = packageLength;
108  if (m_pTransport->read(buffer, remainingBytesToReceive)
109  < static_cast<ITransport::recv_return_t>(remainingBytesToReceive))
110  {
111  std::cout << "Received less than the required " << remainingBytesToReceive << " bytes." << std::endl;
112  return false;
113  }
114 
115  // Check that protocol version and packet type are correct
116  const auto protocolVersion = readUnalignBigEndian<std::uint16_t>(buffer.data());
117  const auto packetType = readUnalignBigEndian<std::uint8_t>(buffer.data() + 2);
118  if (protocolVersion != 0x001)
119  {
120  std::cout << "Received unknown protocol version " << protocolVersion << "." << std::endl;
121  return false;
122  }
123  if (packetType != 0x62)
124  {
125  std::cout << "Received unknown packet type " << packetType << "." << std::endl;
126  return false;
127  }
128  return parseSegmentBinaryData(buffer.begin() + 3, buffer.size() - 3u); // Skip protocolVersion and packetType
129 }
130 
131 bool VisionaryDataStream::parseSegmentBinaryData(std::vector<std::uint8_t>::iterator itBuf, std::size_t bufferSize)
132 {
133  if (m_dataHandler == nullptr)
134  {
135  std::cout << "No datahandler is set -> cant parse blob data" << std::endl;
136  return false;
137  }
138  bool result = false;
139  using ItBufDifferenceType = std::vector<std::uint8_t>::iterator::difference_type;
140  auto itBufSegment = itBuf;
141  auto remainingSize = bufferSize;
142 
143  if (remainingSize < 4)
144  {
145  std::cout << "Received not enough data to parse segment description. Connection issues?" << std::endl;
146  return false;
147  }
148 
149  //-----------------------------------------------
150  // Extract informations in Segment-Binary-Data
151  // const std::uint16_t blobID = readUnalignBigEndian<std::uint16_t>(&*itBufSegment);
152  itBufSegment += sizeof(std::uint16_t);
153  const auto numSegments = readUnalignBigEndian<std::uint16_t>(&*itBufSegment);
154  itBufSegment += sizeof(std::uint16_t);
155  remainingSize -= 4;
156 
157  // offset and changedCounter, 4 bytes each per segment
158  std::vector<std::uint32_t> offset(numSegments);
159  std::vector<std::uint32_t> changeCounter(numSegments);
160  const std::uint16_t segmentDescriptionSize = 4u + 4u;
161  const std::size_t totalSegmentDescriptionSize = static_cast<std::size_t>(numSegments * segmentDescriptionSize);
162  if (remainingSize < totalSegmentDescriptionSize)
163  {
164  std::cout << "Received not enough data to parse segment description. Connection issues?" << std::endl;
165  return false;
166  }
167  if (numSegments < 3)
168  {
169  std::cout << "Invalid number of segments. Connection issues?" << std::endl;
170  return false;
171  }
172  for (std::uint16_t i = 0; i < numSegments; i++)
173  {
174  offset[i] = readUnalignBigEndian<std::uint32_t>(&*itBufSegment);
175  itBufSegment += sizeof(std::uint32_t);
176  changeCounter[i] = readUnalignBigEndian<std::uint32_t>(&*itBufSegment);
177  itBufSegment += sizeof(std::uint32_t);
178  }
179  remainingSize -= totalSegmentDescriptionSize;
180 
181  //-----------------------------------------------
182  // First segment contains the XML Metadata
183  const std::size_t xmlSize = offset[1] - offset[0];
184  if (remainingSize < xmlSize)
185  {
186  std::cout << "Received not enough data to parse xml Description. Connection issues?" << std::endl;
187  return false;
188  }
189  remainingSize -= xmlSize;
190  const std::string xmlSegment((itBuf + static_cast<ItBufDifferenceType>(offset[0])),
191  (itBuf + static_cast<ItBufDifferenceType>(offset[1])));
192  if (m_dataHandler->parseXML(xmlSegment, changeCounter[0]))
193  {
194  //-----------------------------------------------
195  // Second segment contains Binary data
196  std::size_t binarySegmentSize = offset[2] - offset[1];
197  if (remainingSize < binarySegmentSize)
198  {
199  std::cout << "Received not enough data to parse binary Segment. Connection issues?" << std::endl;
200  return false;
201  }
202  result = m_dataHandler->parseBinaryData((itBuf + static_cast<ItBufDifferenceType>(offset[1])), binarySegmentSize);
203  remainingSize -= binarySegmentSize;
204  }
205  return result;
206 }
207 
208 std::shared_ptr<VisionaryData> VisionaryDataStream::getDataHandler()
209 {
210  return m_dataHandler;
211 }
212 
213 void VisionaryDataStream::setDataHandler(std::shared_ptr<VisionaryData> dataHandler)
214 {
215  m_dataHandler = std::move(dataHandler);
216 }
217 
219 {
220  const std::vector<char> data{'B', 'l', 'b', 'R', 'q', 's', 't'};
221  const auto ret = m_pTransport->send(data);
222  // getLastError does not return an error code on windows if send fails
223 #ifdef _WIN32
224  if (ret < 0)
225  {
226  return false;
227  }
228 #else
229  (void)ret;
230 #endif
231  const auto err = m_pTransport->getLastError();
232  return err == 0;
233 }
234 
235 } // namespace visionary
VisionaryEndian.h
visionary::VisionaryDataStream::m_pTransport
std::unique_ptr< ITransport > m_pTransport
Definition: VisionaryDataStream.h:79
visionary::VisionaryDataStream::syncCoLa
bool syncCoLa() const
Definition: VisionaryDataStream.cpp:58
visionary::VisionaryDataStream::getNextFrame
bool getNextFrame()
Definition: VisionaryDataStream.cpp:82
visionary::VisionaryDataStream::VisionaryDataStream
VisionaryDataStream(std::shared_ptr< VisionaryData > dataHandler)
Definition: VisionaryDataStream.cpp:17
visionary::ITransport::recv_return_t
ssize_t recv_return_t
Definition: ITransport.h:29
visionary
Definition: MD5.cpp:44
VisionaryDataStream.h
visionary::VisionaryDataStream::setDataHandler
void setDataHandler(std::shared_ptr< VisionaryData > dataHandler)
Definition: VisionaryDataStream.cpp:213
data
data
visionary::VisionaryDataStream::ByteBuffer
std::vector< std::uint8_t > ByteBuffer
Definition: VisionaryDataStream.h:17
visionary::VisionaryDataStream::close
void close()
Definition: VisionaryDataStream.cpp:49
visionary::VisionaryDataStream::parseSegmentBinaryData
bool parseSegmentBinaryData(const ByteBuffer::iterator itBuf, std::size_t bufferSize)
Definition: VisionaryDataStream.cpp:131
visionary::VisionaryDataStream::~VisionaryDataStream
~VisionaryDataStream()
Definition: VisionaryDataStream.cpp:22
boost::iterators::i
D const & i
Definition: iterator_facade.hpp:956
visionary::VisionaryDataStream::m_dataHandler
std::shared_ptr< VisionaryData > m_dataHandler
Definition: VisionaryDataStream.h:78
std
visionary::VisionaryDataStream::getDataHandler
std::shared_ptr< VisionaryData > getDataHandler()
Definition: VisionaryDataStream.cpp:208
boost::move
BOOST_MOVE_FORCEINLINE ::boost::move_detail::remove_reference< T >::type && move(T &&t) BOOST_NOEXCEPT
Definition: utility_core.hpp:212
visionary::VisionaryDataStream::isConnected
bool isConnected() const
Definition: VisionaryDataStream.cpp:218
visionary::VisionaryDataStream::open
bool open(const std::string &hostname, std::uint16_t port, std::uint32_t timeoutMs=5000u)
Definition: VisionaryDataStream.cpp:27
visionary::TcpSocket
Definition: TcpSocket.h:19


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