test_server_cola_msg.cpp
Go to the documentation of this file.
1 /*
2  * @brief sick_scan2 test_server_cola_msg implements the lidar specific messages,
3  * i.e. message receiving and message creation to simulate lidar devices with
4  * cola communication over tcp.
5  *
6  * Note: sick_scan2 test_server_cola_msg does not implement the functions of lidar sensors,
7  * it just implements a simple message handling to test the sick_scan2 ros drivers.
8  *
9  * Copyright (C) 2020 Ing.-Buero Dr. Michael Lehning, Hildesheim
10  * Copyright (C) 2020 SICK AG, Waldkirch
11  *
12  * Licensed under the Apache License, Version 2.0 (the "License");
13  * you may not use this file except in compliance with the License.
14  * You may obtain a copy of the License at
15  *
16  * http://www.apache.org/licenses/LICENSE-2.0
17  *
18  * Unless required by applicable law or agreed to in writing, software
19  * distributed under the License is distributed on an "AS IS" BASIS,
20  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  * See the License for the specific language governing permissions and
22  * limitations under the License.
23  *
24  * All rights reserved.
25  *
26  * Redistribution and use in source and binary forms, with or without
27  * modification, are permitted provided that the following conditions are met:
28  *
29  * * Redistributions of source code must retain the above copyright
30  * notice, this list of conditions and the following disclaimer.
31  * * Redistributions in binary form must reproduce the above copyright
32  * notice, this list of conditions and the following disclaimer in the
33  * documentation and/or other materials provided with the distribution.
34  * * Neither the name of SICK AG nor the names of its
35  * contributors may be used to endorse or promote products derived from
36  * this software without specific prior written permission
37  * * Neither the name of Ing.-Buero Dr. Michael Lehning nor the names of its
38  * contributors may be used to endorse or promote products derived from
39  * this software without specific prior written permission
40  *
41  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
42  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
45  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
46  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
47  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
48  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
49  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
51  * POSSIBILITY OF SUCH DAMAGE.
52  *
53  * Authors:
54  * Michael Lehning <michael.lehning@lehning.de>
55  *
56  * Copyright 2020 SICK AG
57  * Copyright 2020 Ing.-Buero Dr. Michael Lehning
58  *
59  */
60 #include "sick_scan/binPrintf.hpp"
61 #include "sick_scan/tcp/colaa.hpp"
62 #include "sick_scan/tcp/colab.hpp"
64 
65 static uint8_t calcPayloadChecksum(const std::vector<uint8_t> & payload)
66 {
67  uint8_t checksum = 0;
68  for (int i = 0; i < payload.size(); i++)
69  {
70  checksum = checksum ^ payload[i]; // XOR
71  }
72  return checksum;
73 }
74 
75 static std::vector<uint8_t> encodeColaTelegram(const std::vector<uint8_t> & payload, bool is_binary)
76 {
77  // Encode the telegram (cola-a or cola-b)
78  std::vector<uint8_t> telegram;
79  telegram.reserve(12 + payload.size());
80  if(is_binary)
81  {
82  uint8_t checksum = calcPayloadChecksum(payload);
83  for(int i = 0; i < 4; i++)
84  telegram.push_back(0x02);
85  uint32_t payload_length = payload.size();
86  for(int i = 3; i >= 0; i--)
87  telegram.push_back((payload_length >> (8 * i)) & 0xFF); // payload_length in big endian
88  telegram.insert(telegram.end(), payload.begin(), payload.end());
89  telegram.push_back(checksum);
90  }
91  else
92  {
93  telegram.push_back(0x02); // <STX> := 0x02
94  telegram.insert(telegram.end(), payload.begin(), payload.end());
95  telegram.push_back(0x03); // <ETX> := 0x03
96  }
97  return telegram;
98 }
99 
100 static std::vector<uint8_t> encodeColaTelegram(const std::string & command, const std::vector<std::string> command_parameter, bool is_binary)
101 {
102  std::vector<uint8_t> payload;
103  payload.insert(payload.end(), command.begin(), command.end());
104  for(int n = 0; n < command_parameter.size(); n++)
105  {
106  std::string parameter = command_parameter[n];
107  if(parameter.size() > 254)
108  {
109  parameter.resize(254);
110  ROS_WARN_STREAM("encodeColaTelegram(): resized " << parameter.size() << " byte parameter " << command_parameter[n] << " to " << parameter.size() << " byte parameter " << parameter);
111  }
112  if(is_binary)
113  {
114  if(n == 0)
115  payload.push_back(0x20); // space
116  payload.push_back(0);
117  payload.push_back((uint8_t)(parameter.size() & 0xFF));
118  payload.insert(payload.end(), parameter.begin(), parameter.end());
119  }
120  else
121  {
122  payload.push_back(0x20); // space
123  UINT8 buffer[256];
124  UINT16 len = colaa::addUINT8ToBuffer(buffer, (UINT8)(parameter.size() & 0xFF));
125  for(int i = 0; i < len; i++)
126  payload.push_back(buffer[i]);
127  payload.push_back(0x20); // space
128  payload.insert(payload.end(), parameter.begin(), parameter.end());
129  }
130  }
131  std::vector<uint8_t> telegram = encodeColaTelegram(payload, true);
132  return telegram;
133 }
134 
135 static std::vector<uint8_t> encodeColaTelegram(const std::string & command, const std::vector<int64_t> & parameter_value, const std::vector<size_t> & parameter_size, bool is_binary)
136 {
137  // Encode the payload (cola-a or cola-b)
138  std::vector<uint8_t> payload;
139  assert(parameter_value.size() == parameter_size.size());
140  payload.reserve(command.size() + 16 * parameter_value.size() + 16);
141  payload.insert(payload.end(), command.begin(), command.end());
142  for(int n = 0; n < parameter_value.size(); n++)
143  {
144  if(is_binary)
145  {
146  if(n == 0)
147  payload.push_back(0x20); // space
148  size_t len = parameter_size[n];
149  int64_t value = parameter_value[n];
150  for(int i = len - 1; i >= 0; i--)
151  payload.push_back((value >> (8 * i)) & 0xFF); // Cola-B always in big endian
152  }
153  else
154  {
155  payload.push_back(0x20); // space
156  UINT8 buffer[256];
157  UINT16 len = colaa::addUINT32ToBuffer(buffer, (UINT32)(parameter_value[n] & 0xFFFFFFFF));
158  for(int i = 0; i < len; i++)
159  payload.push_back(buffer[i]);
160  }
161  }
162  // Encode the telegram (cola-a or cola-b)
163  std::vector<uint8_t> telegram = encodeColaTelegram(payload, is_binary);
164  return telegram;
165 }
166 
167 static bool receive(sick_scan_xd::ServerSocket & tcp_client_socket, size_t nr_bytes, bool little_endian, std::vector<uint8_t> & value, bool read_blocking = true)
168 {
169  value.clear();
170  value.resize(nr_bytes);
171  if (!tcp_client_socket.read(nr_bytes, value.data(), read_blocking))
172  return false; // no data available
173  return true;
174 }
175 
176 static bool receive(sick_scan_xd::ServerSocket & tcp_client_socket, size_t nr_bytes, bool little_endian, size_t & value, bool read_blocking = true)
177 {
178  value = 0;
179  std::vector<uint8_t> buffer;
180  if(!receive(tcp_client_socket, nr_bytes, little_endian, buffer, read_blocking) || buffer.size() < nr_bytes)
181  return false; // no data available or communication error
182  if(little_endian)
183  {
184  for(int n = nr_bytes - 1; n >= 0; n--)
185  {
186  value = ((value << 8) | (buffer[n] & 0xFF));
187  }
188  }
189  else
190  {
191  for(int n = 0; n < nr_bytes; n++)
192  {
193  value = ((value << 8) | (buffer[n] & 0xFF));
194  }
195  }
196  return true;
197 }
198 
199 /*
200  * Constructor
201  * @param[in] send_scan_data_rate frequency to generate and send scan data (default: 20 Hz)
202  * @param[in] scan_data_payload scan data payload (without the message header)
203  */
204 sick_scan_xd::test::TestServerColaMsg::TestServerColaMsg(rosNodePtr nh, double send_scan_data_rate, const std::vector<uint8_t> & scan_data_payload)
205 : m_nh(nh), m_send_scan_data_rate(send_scan_data_rate), m_send_scan_data(false), m_send_scan_data_cnt(0)
206 {
207  m_scan_data_payload = scan_data_payload;
208 
209  // Create dictionaries for cola ascii and binary telegrams.
210  // m_colaRequestResponseMap[is_binary?1:0] maps a request (f.e. "sAN SetAccessMode")
211  // to the response payload (f.e. "sAN SetAccessMode 1")
212  std::map<int, std::vector<uint8_t>> sRN_fieldResponses = {
213  { 0, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x4c,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x30,0x30,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x83,0xff,0xff,0x3c,0xb0,0x02,0x01,0x00,0x01,0x00,0x03,0x01,0x2c,0xff,0xff,0x01,0x62,0x01,0xd2,0xff,0xff,0x01,0xa3,0x01,0xe6,0xff,0xff,0x00,0xce,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x0b,0x73,0x65,0x67,0x6d,0x65,0x6e,0x74,0x65,0x64,0x5f,0x31,0x00,0x00,0x6a} },
214  { 1, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x54,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x30,0x31,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x83,0xff,0xff,0x3c,0xb0,0x01,0x02,0x00,0x00,0x00,0x01,0x00,0x0d,0xbb,0xa0,0x00,0x7d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x15,0x72,0x65,0x63,0x74,0x61,0x6e,0x67,0x6c,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x5f,0x30,0x5f,0x64,0x65,0x67,0x00,0x00,0x0d} },
215  { 2, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x4f,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x30,0x32,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x83,0xff,0xff,0x3c,0xb0,0x01,0x03,0x00,0x00,0x00,0x01,0x00,0x0f,0x75,0x6b,0x00,0x7f,0x00,0x06,0xdd,0xd0,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x10,0x72,0x65,0x63,0x74,0x66,0x69,0x65,0x6c,0x64,0x5f,0x34,0x35,0x5f,0x64,0x65,0x67,0x00,0x00,0x0b} },
216  { 3, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x52,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x30,0x33,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x83,0xff,0xff,0x3c,0xb0,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x1b,0x77,0x40,0x00,0xfa,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xe8,0x00,0x00,0x01,0x2c,0x09,0x60,0x00,0x00,0x05,0xdc,0x00,0x01,0x00,0x0d,0x64,0x79,0x6e,0x61,0x6d,0x69,0x63,0x5f,0x66,0x69,0x65,0x6c,0x64,0x00,0x00,0x9a} },
217  { 4, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x2d,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x30,0x34,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x88,0xff,0xff,0x3c,0xb0,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x62} },
218  { 5, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x2d,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x30,0x35,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x88,0xff,0xff,0x3c,0xb0,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x63} },
219  { 6, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x2d,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x30,0x36,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x88,0xff,0xff,0x3c,0xb0,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x60} },
220  { 7, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x2d,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x30,0x37,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x88,0xff,0xff,0x3c,0xb0,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x61} },
221  { 8, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x2d,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x30,0x38,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x88,0xff,0xff,0x3c,0xb0,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x6e} },
222  { 9, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x2d,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x30,0x39,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x88,0xff,0xff,0x3c,0xb0,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x6f} },
223  { 10, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x0e,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x31,0x30,0x20,0x00,0x33} },
224  { 11, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x0e,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x31,0x31,0x20,0x00,0x32} },
225  { 12, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x0e,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x31,0x32,0x20,0x00,0x31} },
226  { 13, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x0e,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x31,0x33,0x20,0x00,0x30} },
227  { 14, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x0e,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x31,0x34,0x20,0x00,0x37} },
228  { 15, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x0e,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x31,0x35,0x20,0x00,0x36} },
229  { 16, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x0e,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x31,0x36,0x20,0x00,0x35} },
230  { 17, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x0e,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x31,0x37,0x20,0x00,0x34} },
231  { 18, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x0e,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x31,0x38,0x20,0x00,0x3b} },
232  { 19, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x0e,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x31,0x39,0x20,0x00,0x3a} },
233  { 20, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x0e,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x32,0x30,0x20,0x00,0x30} },
234  { 21, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x0e,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x32,0x31,0x20,0x00,0x31} },
235  { 22, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x0e,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x32,0x32,0x20,0x00,0x32} },
236  { 23, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x0e,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x32,0x33,0x20,0x00,0x33} },
237  { 24, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x0e,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x32,0x34,0x20,0x00,0x34} },
238  { 25, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x0e,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x32,0x35,0x20,0x00,0x35} },
239  { 26, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x0e,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x32,0x36,0x20,0x00,0x36} },
240  { 27, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x0e,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x32,0x37,0x20,0x00,0x37} },
241  { 28, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x0e,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x32,0x38,0x20,0x00,0x38} },
242  { 29, {0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x0e,0x73,0x52,0x41,0x20,0x66,0x69,0x65,0x6c,0x64,0x30,0x32,0x39,0x20,0x00,0x39} }
243  };
244  for(int is_binary_idx = 0; is_binary_idx <= 1; is_binary_idx++)
245  {
246  m_colaRequestResponseMap[is_binary_idx] = {
247  {"sMN SetAccessMode", encodeColaTelegram("sAN SetAccessMode", {1}, {1}, is_binary_idx > 0)},
248  {"sWN EIHstCola", encodeColaTelegram("sWA EIHstCola", {}, {}, is_binary_idx > 0)},
249  {"sRN FirmwareVersion", encodeColaTelegram("sRA FirmwareVersion", {8, 1, 0, 0, 0}, {2, 1, 1, 1, 1}, is_binary_idx > 0)},
250  {"sRN OrdNum", encodeColaTelegram("sRA OrdNum", {7, 1234567}, {1, 4}, is_binary_idx > 0)},
251  {"sWN TransmitTargets", encodeColaTelegram("sWA TransmitTargets", {}, {}, is_binary_idx > 0)},
252  {"sWN TransmitObjects", encodeColaTelegram("sWA TransmitObjects", {}, {}, is_binary_idx > 0)},
253  {"sWN TCTrackingMode", encodeColaTelegram("sWA TCTrackingMode", {}, {}, is_binary_idx > 0)},
254  {"sRN SCdevicestate", encodeColaTelegram("sRA SCdevicestate", {1}, {1}, is_binary_idx > 0)},
255  {"sRN DItype", encodeColaTelegram("sRA DItype F RMS2731C.636111", {}, {}, is_binary_idx > 0)},
256  {"sRN ODoprh", encodeColaTelegram("sRA ODoprh", {451}, {2}, is_binary_idx > 0)},
257  {"sMN mSCloadappdef", encodeColaTelegram("sAN mSCloadappdef", {}, {}, is_binary_idx > 0)},
258  {"sRN SerialNumber", encodeColaTelegram("sRA SerialNumber", {"18340008"}, is_binary_idx > 0)},
259  {"sRN ODpwrc", encodeColaTelegram("sRA ODpwrc", {20}, {1}, is_binary_idx > 0)},
260  {"sRN LocationName", encodeColaTelegram("sRA LocationName B not defined", {}, {}, is_binary_idx > 0)},
261  {"sEN LMDradardata", encodeColaTelegram("sEA LMDradardata", {1}, {1}, is_binary_idx > 0)},
262  {"sRN LMPoutputRange", encodeColaTelegram("sRA LMPoutputRange", {1, 2500, -450000, 1850000}, {2, 4, 4, 4}, is_binary_idx > 0)},
263  {"sWN LMPoutputRange", encodeColaTelegram("sWA LMPoutputRange", {}, {}, is_binary_idx > 0)},
264  {"sWN LMDscandatacfg", encodeColaTelegram("sWA LMDscandatacfg", {}, {}, is_binary_idx > 0)},
265  {"sRN LMDscandatacfg", encodeColaTelegram("sRA LMDscandatacfg", {1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, is_binary_idx > 0)},
266  {"sWN SetActiveApplications", encodeColaTelegram("sWA SetActiveApplications", {}, {}, is_binary_idx > 0)},
267  {"sWN FREchoFilter", encodeColaTelegram("sWA FREchoFilter", {}, {}, is_binary_idx > 0)},
268  {"sEN InertialMeasurementUnit", encodeColaTelegram("sEA InertialMeasurementUnit", {}, {}, is_binary_idx > 0)},
269  {"sRN DeviceIdent", encodeColaTelegram("sRA DeviceIdent", {"MRS1xxxC", "1.4.3.0B"}, is_binary_idx > 0)}, // todo: DeviceIdent from config // DeviceIdent 8 MRS1xxxx 8 1.3.0.0R.
270  {"sMN LMCstartmeas", encodeColaTelegram("sAN LMCstartmeas", {}, {}, is_binary_idx > 0)},
271  {"sMN LMCstopmeas", encodeColaTelegram("sAN LMCstopmeas", {}, {}, is_binary_idx > 0)},
272  {"sMN Run", encodeColaTelegram("sAN Run", {}, {}, is_binary_idx > 0)},
273  {"sEN LMDscandata", encodeColaTelegram("sEA LMDscandata", {}, {}, is_binary_idx > 0)},
274  {"sRN field000", sRN_fieldResponses[0]},
275  {"sRN field001", sRN_fieldResponses[1]},
276  {"sRN field002", sRN_fieldResponses[2]},
277  {"sRN field003", sRN_fieldResponses[3]},
278  {"sRN field004", sRN_fieldResponses[4]},
279  {"sRN field005", sRN_fieldResponses[5]},
280  {"sRN field006", sRN_fieldResponses[6]},
281  {"sRN field007", sRN_fieldResponses[7]},
282  {"sRN field008", sRN_fieldResponses[8]},
283  {"sRN field009", sRN_fieldResponses[9]},
284  {"sRN field010", sRN_fieldResponses[10]},
285  {"sRN field011", sRN_fieldResponses[11]},
286  {"sRN field012", sRN_fieldResponses[12]},
287  {"sRN field013", sRN_fieldResponses[13]},
288  {"sRN field014", sRN_fieldResponses[14]},
289  {"sRN field015", sRN_fieldResponses[15]},
290  {"sRN field016", sRN_fieldResponses[16]},
291  {"sRN field017", sRN_fieldResponses[17]},
292  {"sRN field018", sRN_fieldResponses[18]},
293  {"sRN field019", sRN_fieldResponses[19]},
294  {"sRN field020", sRN_fieldResponses[20]},
295  {"sRN field021", sRN_fieldResponses[21]},
296  {"sRN field022", sRN_fieldResponses[22]},
297  {"sRN field023", sRN_fieldResponses[23]},
298  {"sRN field024", sRN_fieldResponses[24]},
299  {"sRN field025", sRN_fieldResponses[25]},
300  {"sRN field026", sRN_fieldResponses[26]},
301  {"sRN field027", sRN_fieldResponses[27]},
302  {"sRN field028", sRN_fieldResponses[28]},
303  {"sRN field029", sRN_fieldResponses[29]}
304  };
305  }
306 }
307 
308 /*
309  * @brief Receives a cola telegram if data on a tcp socket are available.
310  * Non-blocking function (i.e. it returns immediately) if no data available.
311  * If data available, this function returns after a complete message has been received, or an error occured.
312  * @param[in] tcp_client_socket socket to read from
313  * @param[out] message cola telegram received from client (without the leading <STX> or trailing <ETX> bytes)
314  * @param[out] is_binary always true for LDMRS
315  * @return true, if a cola telegram has been received, false otherwise
316  */
317 bool sick_scan_xd::test::TestServerColaMsg::receiveMessage(sick_scan_xd::ServerSocket & tcp_client_socket, std::vector<uint8_t> & cola_telegram, bool & is_binary)
318 {
319  is_binary = false;
320  cola_telegram.clear();
321  // Receive <STX>
322  size_t stx_received = 0, payload_length = 0;
323  if (!receive(tcp_client_socket, 4, false, stx_received, false))
324  return false; // no data available
325  if(stx_received == 0x02020202) // i.e. binary Cola-B
326  {
327  is_binary = true;
328  // Read payload length and payload
329  // telegram length := 8 byte header + payload_length + 1 byte checksum
330  if (!receive(tcp_client_socket, 4, false, payload_length))
331  return false; // no data available
332  if (!receive(tcp_client_socket, payload_length + 1, false, cola_telegram))
333  return false; // communication error
334  cola_telegram.pop_back(); // 1 byte checksum currently ignored
335  return true;
336  }
337  else if(((stx_received >> 24) & 0xFF) == 0x02) // i.e. Ascii Cola-A
338  {
339  cola_telegram.reserve(1024);
340  cola_telegram.push_back((stx_received >> 16) & 0xFF);
341  cola_telegram.push_back((stx_received >> 8) & 0xFF);
342  cola_telegram.push_back((stx_received) & 0xFF);
343  // Read until "<ETX>" := 0x03
344  uint8_t byte = 0;
345  while(tcp_client_socket.read(1, &byte))
346  {
347  if(byte == 0x03)
348  break;
349  cola_telegram.push_back(byte);
350  }
351  if(byte != 0x03)
352  return false; // communication error, <ETX> not received
353  return true;
354  }
355  else
356  {
357  ROS_ERROR_STREAM("sick_scan_xd::test::TestServerColaMsg::receiveMessage(): received 4 byte 0x" << std::hex << stx_received << ", expected <STX>");
358  return false;
359  }
360 }
361 
362 /*
363  * @brief Generate a response to a message received from client.
364  * @param[in] message_received message received from client (without the leading <STX> or trailing <ETX> bytes)
365  * @param[in] is_binary true for binary messages, false for ascii messages
366  * @param[out] response response to the client
367  * @return true, if a response has been created, false otherwise (no response required or invalid message received)
368  */
369 bool sick_scan_xd::test::TestServerColaMsg::createResponse(const std::vector<uint8_t> & message_received, bool is_binary, std::vector<uint8_t> & response)
370 {
371  response.clear();
372  // ROS_INFO_STREAM("sick_scan_xd::test::TestServerColaMsg::createResponse(): received cola-" << (is_binary?"b":"a") << " telegram \"" << binDumpVecToString(&message_received, true) << "\"");
373  // Get response from dictionary
374  std::string received_str(message_received.begin(), message_received.end());
375  const std::map<std::string, std::vector<uint8_t>> & colaRequestResponseMap = m_colaRequestResponseMap[is_binary?1:0];
376  for(std::map<std::string, std::vector<uint8_t>>::const_iterator iter = colaRequestResponseMap.cbegin(); iter != colaRequestResponseMap.cend(); iter++)
377  {
378  if(received_str.find(iter->first) != std::string::npos)
379  {
380  response = iter->second;
381  break;
382  }
383  }
384  // Check start / stop scan data
385  int send_scan_data = -1;
386  if(received_str.find("sEN LMDscandata ") != std::string::npos && message_received.size() > 16) // start / stop scan data command
387  {
388  if(is_binary && message_received[16] == 0x00)
389  send_scan_data = 0;
390  else if(!is_binary && message_received[16] == '0')
391  send_scan_data = 0;
392  else
393  send_scan_data = 1;
394  }
395  else if(received_str.find("sMN LMCstartmeas") != std::string::npos)
396  send_scan_data = 1;
397  else if(received_str.find("sMN LMCstopmeas") != std::string::npos)
398  send_scan_data = 0;
399  if(send_scan_data >= 0) // start / stop scan data command received
400  {
401  m_send_scan_data = ((send_scan_data > 0) ? true : false);
402  if(m_send_scan_data)
403  m_last_scan_data = std::chrono::system_clock::now(); // start scan data with the next cycle
404  ROS_INFO_STREAM("sick_scan_xd::test::TestServerThread::createResponse(): received " << message_received.size()
405  << " byte message " << binDumpVecToString(&message_received, true) << " -> " << (m_send_scan_data ? "start" : "stop") << " sending scan data");
406  }
407  return response.size() > 0;
408 }
409 
410 /*
411  * @brief Generate a scan data message.
412  * @param[out] scandata scan data message
413  * @return true, if a a scan data message has been created, false otherwise (f.e. if a sensor does not generate scan data)
414  */
415 bool sick_scan_xd::test::TestServerColaMsg::createScandata(std::vector<uint8_t> & scandata)
416 {
417  scandata.clear();
418  if(!m_send_scan_data || std::chrono::duration<double>(std::chrono::system_clock::now() - m_last_scan_data).count() < 1/m_send_scan_data_rate) // frequency to generate and send scan data (default: 20 Hz)
419  {
420  return false; // scan data disabled
421  }
422 
423  // Encode example scan data
424  std::string command = "sRA LMDscandata ";
425  std::vector<uint8_t> payload;
426  payload.reserve(command.size() + m_scan_data_payload.size() + 16);
427  payload.insert(payload.end(), command.begin(), command.end());
428  payload.insert(payload.end(), m_scan_data_payload.begin(), m_scan_data_payload.end());
429  scandata = encodeColaTelegram(payload, true);
430 
431  // Increase counter and range for the next scan
432  m_last_scan_data = std::chrono::system_clock::now();
433  m_send_scan_data_cnt += 1;
434  ROS_DEBUG_STREAM("sick_scan_xd::test::TestServerColaMsg::createScandata(" << m_send_scan_data_cnt << "): " << scandata.size() << " byte scan data generated");
435  if(m_send_scan_data_cnt <= 1)
436  ROS_DEBUG_STREAM("sick_scan_xd::test::TestServerColaMsg::createScandata(): Generating " << scandata.size() << " byte scan data with " << m_send_scan_data_rate << " Hz");
437 
438  return true;
439 }
response
const std::string response
UINT16
uint16_t UINT16
Definition: BasicDatatypes.hpp:73
UINT8
uint8_t UINT8
Definition: BasicDatatypes.hpp:75
binDumpVecToString
std::string binDumpVecToString(const std::vector< unsigned char > *outvec, bool appendReadableText)
Definition: binPrintf.cpp:264
calcPayloadChecksum
static uint8_t calcPayloadChecksum(const std::vector< uint8_t > &payload)
Definition: test_server_cola_msg.cpp:65
colaa::addUINT8ToBuffer
UINT16 addUINT8ToBuffer(UINT8 *buffer, UINT8 value)
Definition: colaa.cpp:111
ROS::now
ROS::Time now(void)
Definition: ros_wrapper.cpp:116
test_server_cola_msg.h
pcap_json_converter.payload
string payload
Definition: pcap_json_converter.py:130
encodeColaTelegram
static std::vector< uint8_t > encodeColaTelegram(const std::vector< uint8_t > &payload, bool is_binary)
Definition: test_server_cola_msg.cpp:75
colab.hpp
ROS_WARN_STREAM
#define ROS_WARN_STREAM(args)
Definition: sick_scan_logging.h:123
ROS_INFO_STREAM
#define ROS_INFO_STREAM(...)
Definition: sick_scan_ros2_example.cpp:71
sick_scan_xd::test::TestServerColaMsg::receiveMessage
virtual bool receiveMessage(sick_scan_xd::ServerSocket &tcp_client_socket, std::vector< uint8_t > &message, bool &is_binary)
Definition: test_server_cola_msg.cpp:317
binPrintf.hpp
ROS_DEBUG_STREAM
#define ROS_DEBUG_STREAM(args)
Definition: sick_scan_logging.h:113
sick_scan_xd::test::TestServerColaMsg::m_colaRequestResponseMap
std::map< std::string, std::vector< uint8_t > > m_colaRequestResponseMap[2]
Definition: test_server_cola_msg.h:116
ros::NodeHandle
sick_scan_xd::test::TestServerColaMsg::createScandata
virtual bool createScandata(std::vector< uint8_t > &scandata)
Definition: test_server_cola_msg.cpp:415
sick_scan_xd::test::TestServerColaMsg::createResponse
virtual bool createResponse(const std::vector< uint8_t > &message_received, bool is_binary, std::vector< uint8_t > &response)
Definition: test_server_cola_msg.cpp:369
colaa::addUINT32ToBuffer
UINT16 addUINT32ToBuffer(UINT8 *buffer, UINT32 value)
Definition: colaa.cpp:200
sick_scan_xd::test::TestServerColaMsg::TestServerColaMsg
TestServerColaMsg(rosNodePtr nh, double send_scan_data_rate=20.0, const std::vector< uint8_t > &scan_data_payload=std::vector< uint8_t >())
Definition: test_server_cola_msg.cpp:204
colaa.hpp
sick_scan_xd::test::TestServerColaMsg::m_scan_data_payload
std::vector< uint8_t > m_scan_data_payload
Definition: test_server_cola_msg.h:119
ROS_ERROR_STREAM
#define ROS_ERROR_STREAM(...)
Definition: sick_scan_ros2_example.cpp:72
UINT32
uint32_t UINT32
Definition: BasicDatatypes.hpp:72
receive
static bool receive(sick_scan_xd::ServerSocket &tcp_client_socket, size_t nr_bytes, bool little_endian, std::vector< uint8_t > &value, bool read_blocking=true)
Definition: test_server_cola_msg.cpp:167
roswrap::package::command
ROSLIB_DECL std::string command(const std::string &cmd)
Runs a rospack command of the form 'rospack <cmd>', returning the output as a single string.
sick_scan_xd::ServerSocket::read
virtual int read(int num_bytes, std::vector< uint8_t > &out_buffer, bool read_blocking=true)
Definition: server_socket.cpp:197
sick_scan_xd::ServerSocket
Definition: server_socket.h:83


sick_scan_xd
Author(s): Michael Lehning , Jochen Sprickerhof , Martin Günther
autogenerated on Fri Oct 25 2024 02:47:12