messageextractor.cpp
Go to the documentation of this file.
1 
2 // Copyright (c) 2003-2021 Xsens Technologies B.V. or subsidiaries worldwide.
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification,
6 // are permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice,
9 // this list of conditions, and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice,
12 // this list of conditions, and the following disclaimer in the documentation
13 // and/or other materials provided with the distribution.
14 //
15 // 3. Neither the names of the copyright holders nor the names of their contributors
16 // may be used to endorse or promote products derived from this software without
17 // specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
20 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 // THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
24 // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
26 // TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.THE LAWS OF THE NETHERLANDS
28 // SHALL BE EXCLUSIVELY APPLICABLE AND ANY DISPUTES SHALL BE FINALLY SETTLED UNDER THE RULES
29 // OF ARBITRATION OF THE INTERNATIONAL CHAMBER OF COMMERCE IN THE HAGUE BY ONE OR MORE
30 // ARBITRATORS APPOINTED IN ACCORDANCE WITH SAID RULES.
31 //
32 
33 
34 // Copyright (c) 2003-2021 Xsens Technologies B.V. or subsidiaries worldwide.
35 // All rights reserved.
36 //
37 // Redistribution and use in source and binary forms, with or without modification,
38 // are permitted provided that the following conditions are met:
39 //
40 // 1. Redistributions of source code must retain the above copyright notice,
41 // this list of conditions, and the following disclaimer.
42 //
43 // 2. Redistributions in binary form must reproduce the above copyright notice,
44 // this list of conditions, and the following disclaimer in the documentation
45 // and/or other materials provided with the distribution.
46 //
47 // 3. Neither the names of the copyright holders nor the names of their contributors
48 // may be used to endorse or promote products derived from this software without
49 // specific prior written permission.
50 //
51 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
52 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
53 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
54 // THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 // SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
56 // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
58 // TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
59 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.THE LAWS OF THE NETHERLANDS
60 // SHALL BE EXCLUSIVELY APPLICABLE AND ANY DISPUTES SHALL BE FINALLY SETTLED UNDER THE RULES
61 // OF ARBITRATION OF THE INTERNATIONAL CHAMBER OF COMMERCE IN THE HAGUE BY ONE OR MORE
62 // ARBITRATORS APPOINTED IN ACCORDANCE WITH SAID RULES.
63 //
64 
65 #include "messageextractor.h"
66 #include "xscontrollerconfig.h"
67 #include <xstypes/xsmessagearray.h>
68 
83 MessageExtractor::MessageExtractor(std::shared_ptr<IProtocolManager> const& protocolManager)
84  : m_protocolManager(protocolManager)
85  , m_retryTimeout(0)
86  , m_buffer()
87  , m_maxIncompleteRetryCount(5)
88 {
89 }
90 
98 XsResultValue MessageExtractor::processNewData(XsDevice* devicePtr, XsByteArray const& newData, std::deque<XsMessage>& messages)
99 {
100  if (!m_protocolManager)
101  return XRV_ERROR;
102 
103 #ifdef XSENS_DEBUG
104  XsSize prevSize = m_buffer.size();
105 #endif
106  if (newData.size())
107  m_buffer.append(newData);
108 #ifdef XSENS_DEBUG
109  assert(m_buffer.size() == newData.size() + prevSize);
110 #endif
111 
112  XsSize popped = 0;
113  messages.clear();
114 
115  while (true)
116  {
117  assert(popped <= m_buffer.size());
118 
119  XsByteArray raw(m_buffer.data() + popped, m_buffer.size() - popped, XSDF_None);
120 
121  XsProtocolType type;
122  MessageLocation location = m_protocolManager->findMessage(type, raw);
123  assert(location.m_startPos == -1 || location.m_incompletePos == -1 || location.m_incompletePos < location.m_startPos);
124 
125  if (location.isValid())
126  {
127  XsByteArray detectedMessage(&raw[(XsSize)(ptrdiff_t) location.m_startPos], (XsSize)(ptrdiff_t) location.m_size, XSDF_None);
128  if (devicePtr != nullptr)
129  devicePtr->onMessageDetected2(type, detectedMessage);
130 
131  XsMessage message = m_protocolManager->convertToMessage(type, location, raw);
132  assert(location.m_startPos == -1 || location.m_incompletePos == -1 || location.m_incompletePos < location.m_startPos);
133 
134  if (location.isValid() && !message.empty() && m_protocolManager->validateMessage(message))
135  {
136  // We are going to skip something
137  if (location.m_incompletePos != -1)
138  {
139  // We are going to skip an incomplete but potentially valid message
140  // First wait a couple of times to see if we can complete that message before skipping
142  {
143  // wait a bit until we have more data
144  // but already pop the data that we know contains nothing useful
145  if (location.m_incompletePos > 0)
146  {
147  JLALERTG("Skipping " << location.m_incompletePos << " bytes from the input buffer");
148  popped += (XsSize)(ptrdiff_t) location.m_incompletePos;
149  }
150 
151  break;
152  }
153  else
154  {
155  // We've waited a bit for the incomplete message to complete but it never completed
156  // So: We are going to skip an incomplete but potentially valid message
157  JLALERTG("Skipping " << location.m_startPos << " bytes from the input buffer that may contain an incomplete message at " << location.m_incompletePos
158  << " found: " << (int)message.getTotalMessageSize()
159  << std::hex << std::setfill('0')
160  << " First bytes " << std::setw(2) << (int)message.getMessageStart()[0]
161  << " " << std::setw(2) << (int)message.getMessageStart()[1]
162  << " " << std::setw(2) << (int)message.getMessageStart()[2]
163  << " " << std::setw(2) << (int)message.getMessageStart()[3]
164  << " " << std::setw(2) << (int)message.getMessageStart()[4]
165  << std::dec << std::setfill(' '));
166  }
167  }
168  else if (location.m_startPos > 0)
169  {
170  // We are going to skip something but we are not going to skip an incomplete but potentially valid message
171  JLALERTG("Skipping " << location.m_startPos << " bytes from the input buffer");
172  }
173 
174  if (m_retryTimeout)
175  {
176  JLTRACEG("Resetting retry count from " << m_retryTimeout);
177  m_retryTimeout = 0;
178  }
179 
180  // message is valid, remove data from cache
181  popped += (XsSize)(ptrdiff_t)(location.m_size + location.m_startPos);
182  messages.push_back(message);
183  }
184  else
185  {
186  if (type == XPT_Nmea)
187  popped += (XsSize)(ptrdiff_t)(location.m_size + location.m_startPos);
188  else
189  break;
190  }
191  }
192  else
193  {
194  int bestPosition = location.m_incompletePos >= 0 ? location.m_incompletePos : location.m_startPos;
195  if (bestPosition < 0)
196  popped = m_buffer.size();
197  else
198  popped += (XsSize)(ptrdiff_t)bestPosition;
199  break;
200  }
201  }
202 
203  if (popped > 0)
204  m_buffer.pop_front(popped);
205  if (messages.empty())
206  return XRV_TIMEOUTNODATA;
207 
208  return XRV_OK;
209 }
210 
214 {
215  JLDEBUGG(this);
216  m_buffer.clear();
217 }
218 
224 {
225  int rv = m_maxIncompleteRetryCount;
227  return rv;
228 }
messageextractor.h
XsDevice::onMessageDetected2
virtual XSNOEXPORT void onMessageDetected2(XsProtocolType type, const XsByteArray &rawMessage)
XsByteArray
A list of uint8_t values.
MessageExtractor::m_buffer
XsByteArray m_buffer
Definition: messageextractor.h:88
JLALERTG
#define JLALERTG(msg)
Definition: journaller.h:281
xsmessagearray.h
XRV_TIMEOUTNODATA
@ XRV_TIMEOUTNODATA
259: Operation aborted because of no data read
Definition: xsresultvalue.h:129
XRV_ERROR
@ XRV_ERROR
256: A generic error occurred
Definition: xsresultvalue.h:126
XRV_OK
@ XRV_OK
0: Operation was performed successfully
Definition: xsresultvalue.h:85
XsResultValue
XsResultValue
Xsens result values.
Definition: xsresultvalue.h:82
XPT_Nmea
@ XPT_Nmea
The NMEA protocol, only the messages that can be sent from Xsens devices are recognized.
Definition: xsprotocoltype.h:75
MessageExtractor::m_maxIncompleteRetryCount
int m_maxIncompleteRetryCount
Definition: messageextractor.h:89
MessageExtractor::MessageExtractor
MessageExtractor(std::shared_ptr< IProtocolManager > const &protocolManager)
Constructor.
Definition: messageextractor.cpp:83
MessageLocation::m_size
int m_size
The size of the message, when less than 0 it indicates the expected message size.
Definition: messagelocation.h:74
JLTRACEG
#define JLTRACEG(msg)
Definition: journaller.h:279
XsSize
size_t XsSize
XsSize must be unsigned number!
Definition: xstypedefs.h:74
XsMessage
Structure for storing a single message.
Definition: xsmessage.h:202
MessageExtractor::m_retryTimeout
int m_retryTimeout
Definition: messageextractor.h:87
MessageLocation::m_incompletePos
int m_incompletePos
Definition: messagelocation.h:82
XSDF_None
@ XSDF_None
No flag set.
Definition: xstypedefs.h:109
JLDEBUGG
#define JLDEBUGG(msg)
Definition: journaller.h:280
MessageExtractor::setMaxIncompleteRetryCount
int setMaxIncompleteRetryCount(int max)
Sets the maximum number of process attempts before advancing over an incompletely received message.
Definition: messageextractor.cpp:223
XsProtocolType
XsProtocolType
Protocol types (XsDevice::enableProtocol())
Definition: xsprotocoltype.h:72
MessageExtractor::clearBuffer
void clearBuffer()
Clears the processing buffer.
Definition: messageextractor.cpp:213
MessageExtractor::processNewData
XsResultValue processNewData(XsDevice *devicePtr, XsByteArray const &newData, std::deque< XsMessage > &messages)
Processes new incoming data for message extraction.
Definition: messageextractor.cpp:98
MessageExtractor::m_protocolManager
std::shared_ptr< IProtocolManager > m_protocolManager
Definition: messageextractor.h:86
XsDevice
Definition: xsdevice_def.h:164
MessageLocation
Stores the location of a message in a buffer using a start position and a size.
Definition: messagelocation.h:70
MessageLocation::m_startPos
int m_startPos
The offset of the first byte of the message or -1 if no message.
Definition: messagelocation.h:73
MessageLocation::isValid
bool isValid() const
Returns whether the stored message information describes a valid message.
Definition: messagelocation.h:107
xscontrollerconfig.h


xsens_mti_driver
Author(s):
autogenerated on Sun Sep 3 2023 02:43:20