75 : m_ip_port_results(ip_port_results), m_ip_port_cola(ip_port_cola), m_ioservice(),
76 m_tcp_connection_thread_results(0), m_tcp_connection_thread_cola(0), m_tcp_send_scandata_thread(0),
77 m_tcp_connection_thread_running(false), m_worker_thread_running(false), m_tcp_send_scandata_thread_running(false),
78 m_tcp_acceptor_results(m_ioservice,
boost::asio::ip::tcp::endpoint(
boost::asio::ip::tcp::v4(), m_ip_port_results)),
79 m_tcp_acceptor_cola(m_ioservice,
boost::asio::ip::tcp::endpoint(
boost::asio::ip::tcp::v4(), m_ip_port_cola)),
80 m_start_scandata_delay(1), m_result_telegram_rate(10), m_demo_move_in_circles(false), m_error_simulation_enabled(false), m_error_simulation_flag(
NO_ERROR),
81 m_error_simulation_thread(0), m_error_simulation_thread_running(false)
92 std::string result_testcases_topic =
"/sick_scan/test_server/result_testcases";
94 ROS::param<std::string>(nh,
"/sick_scan/test_server/result_testcases_topic", result_testcases_topic, result_testcases_topic);
98 std::string sim_loc_test_server_demo_circles, sim_loc_test_server_error_simulation;
99 ROS::param<std::string>(nh,
"/system/test_server/demo_circles", sim_loc_test_server_demo_circles, sim_loc_test_server_demo_circles);
100 ROS::param<std::string>(nh,
"/system/test_server/error_simulation", sim_loc_test_server_error_simulation, sim_loc_test_server_error_simulation);
101 if(!sim_loc_test_server_demo_circles.empty())
103 if(!sim_loc_test_server_error_simulation.empty())
124 if(m_error_simulation_enabled)
126 ROS_WARN_STREAM(
"TestServerThread: running in error simulation mode.");
127 ROS_WARN_STREAM(
"Test server will intentionally react incorrect and will send false data and produce communication errors.");
128 ROS_WARN_STREAM(
"Running test server in error simulation mode is for test purposes only. Do not expect typical results.");
129 m_error_simulation_thread_running =
true;
132 else if(m_demo_move_in_circles)
134 ROS_INFO_STREAM(
"TestServerThread: running in demo mode (moving in circles, no error simulation).");
138 ROS_INFO_STREAM(
"TestServerThread: running in normal mode (no error simulation).");
141 m_tcp_connection_thread_running =
true;
153 m_tcp_connection_thread_running =
false;
154 m_error_simulation_thread_running =
false;
155 m_worker_thread_running =
false;
156 if(m_error_simulation_thread)
158 m_error_simulation_thread->join();
159 delete(m_error_simulation_thread);
160 m_error_simulation_thread = 0;
164 std::vector<boost::asio::ip::tcp::acceptor*> tcp_acceptors = { &m_tcp_acceptor_results, & m_tcp_acceptor_cola };
165 for(std::vector<boost::asio::ip::tcp::acceptor*>::iterator iter_acceptor = tcp_acceptors.begin(); iter_acceptor != tcp_acceptors.end(); iter_acceptor++)
167 if((*iter_acceptor)->is_open())
169 (*iter_acceptor)->cancel();
170 (*iter_acceptor)->close();
174 std::vector<thread_ptr*> tcp_connection_threads = { &m_tcp_connection_thread_results, &m_tcp_connection_thread_cola };
175 for(std::vector<thread_ptr*>::iterator iter_connection_thread = tcp_connection_threads.begin(); iter_connection_thread != tcp_connection_threads.end(); iter_connection_thread++)
177 thread_ptr & tcp_connection_thread = **iter_connection_thread;
178 if(tcp_connection_thread)
180 tcp_connection_thread->join();
181 delete(tcp_connection_thread);
182 tcp_connection_thread = 0;
186 closeScandataThread();
188 closeTcpConnections();
190 closeWorkerThreads();
199 if(m_tcp_send_scandata_thread)
201 m_tcp_send_scandata_thread_running =
false;
202 m_tcp_send_scandata_thread->join();
203 delete(m_tcp_send_scandata_thread);
204 m_tcp_send_scandata_thread = 0;
214 for(std::list<boost::asio::ip::tcp::socket*>::iterator socket_iter = m_tcp_sockets.begin(); socket_iter != m_tcp_sockets.end(); socket_iter++)
216 boost::asio::ip::tcp::socket* p_socket = *socket_iter;
219 if(p_socket && (force_shutdown || p_socket->is_open()))
221 p_socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both);
225 catch(std::exception & exc)
227 ROS_WARN_STREAM(
"TestServerThread::closeTcpConnections(): exception " << exc.what() <<
" on closing socket.");
231 m_tcp_sockets.clear();
240 boost::lock_guard<boost::mutex> worker_thread_lockguard(m_tcp_worker_threads_mutex);
243 if(p_socket && p_socket->is_open())
245 p_socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both);
250 for(std::list<boost::asio::ip::tcp::socket*>::iterator socket_iter = m_tcp_sockets.begin(); socket_iter != m_tcp_sockets.end(); )
252 if(p_socket == *socket_iter)
253 socket_iter = m_tcp_sockets.erase(socket_iter);
260 catch(std::exception & exc)
262 ROS_WARN_STREAM(
"TestServerThread::closeSocket(): exception " << exc.what() <<
" on closing socket.");
271 m_worker_thread_running =
false;
272 boost::lock_guard<boost::mutex> worker_thread_lockguard(m_tcp_worker_threads_mutex);
273 for(std::list<thread_ptr>::iterator thread_iter = m_tcp_worker_threads.begin(); thread_iter != m_tcp_worker_threads.end(); thread_iter++)
275 boost::thread *p_thread = *thread_iter;
279 m_tcp_worker_threads.clear();
289 m_last_telegram_received.set(
msg);
317 while(ROS::ok() && m_tcp_connection_thread_running && tcp_acceptor_results.is_open())
319 if(m_error_simulation_flag.get() == DONT_LISTEN)
325 boost::asio::ip::tcp::socket* tcp_client_socket =
new boost::asio::ip::tcp::socket(m_ioservice);
326 boost::system::error_code errorcode;
327 if(m_error_simulation_flag.get() != DONT_LISTEN && m_error_simulation_flag.get() != DONT_ACCECPT)
328 ROS_INFO_STREAM(
"TestServerThread: listening to tcp connections on port " << ip_port_results);
329 tcp_acceptor_results.listen();
330 if(m_error_simulation_flag.get() == DONT_LISTEN || m_error_simulation_flag.get() == DONT_ACCECPT)
335 tcp_acceptor_results.accept(*tcp_client_socket, errorcode);
336 if(m_error_simulation_flag.get() == DONT_LISTEN || m_error_simulation_flag.get() == DONT_ACCECPT)
338 if(tcp_client_socket->is_open())
340 tcp_client_socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both);
341 tcp_client_socket->close();
346 if (!errorcode && tcp_client_socket->is_open())
349 ROS_INFO_STREAM(
"TestServerThread: established new tcp client connection");
350 boost::lock_guard<boost::mutex> worker_thread_lockguard(m_tcp_worker_threads_mutex);
351 m_tcp_sockets.push_back(tcp_client_socket);
352 m_worker_thread_running =
true;
353 m_tcp_worker_threads.push_back(
new boost::thread(thread_function_cb,
this, tcp_client_socket));
356 closeTcpConnections();
357 m_tcp_connection_thread_running =
false;
368 ROS_INFO_STREAM(
"TestServerThread: worker thread for result telegrams started");
372 double circle_yaw = 0;
373 while(ROS::ok() && m_worker_thread_running && p_socket && p_socket->is_open())
376 boost::system::error_code error_code;
377 if (m_error_simulation_flag.get() == DONT_SEND)
379 ROS_DEBUG_STREAM(
"TestServerThread for cresult telegrams: error simulation, server not sending any telegrams");
382 if (m_error_simulation_flag.get() == SEND_RANDOM_TCP)
384 std::vector<uint8_t> random_data = random_generator.
generate(random_length.
generate());
385 boost::asio::write(*p_socket, boost::asio::buffer(random_data.data(), random_data.size()), boost::asio::transfer_exactly(random_data.size()), error_code);
391 if(m_demo_move_in_circles)
396 if (m_error_simulation_flag.get() == SEND_INVALID_TELEGRAMS)
398 int number_random_bytes = ((random_integer.
generate()) % (testcase.binary_data.size()));
399 for(
int cnt_random_bytes = 0; cnt_random_bytes < number_random_bytes; cnt_random_bytes++)
401 int byte_cnt = ((random_integer.
generate()) % (testcase.binary_data.size()));
402 testcase.binary_data[byte_cnt] = (uint8_t)(random_generator.
generate() & 0xFF);
409 size_t bytes_written = boost::asio::write(*p_socket, boost::asio::buffer(testcase.binary_data.data(), testcase.binary_data.size()), boost::asio::transfer_exactly(testcase.binary_data.size()), error_code);
410 if (error_code || bytes_written != testcase.binary_data.size())
412 std::stringstream error_info;
413 error_info <<
"## ERROR TestServerThread for result telegrams: failed to send binary result port telegram, " << bytes_written <<
" of " << testcase.binary_data.size() <<
" bytes send, error code: " << error_code.message();
414 if (m_error_simulation_flag.get() ==
NO_ERROR)
416 ROS_WARN_STREAM(error_info.str() <<
", close socket and leave worker thread for result telegrams");
427 testcase.header.frame_id = m_result_testcases_frame_id;
428 ROS_PUBLISH(m_result_testcases_publisher, testcase);
431 closeSocket(p_socket);
432 ROS_INFO_STREAM(
"TestServerThread: worker thread for result telegrams finished");
443 ROS_INFO_STREAM(
"TestServerThread: worker thread for command requests started");
444 int iTransmitErrorCnt = 0;
448 while(ROS::ok() && m_worker_thread_running && p_socket && p_socket->is_open())
452 ROS::Time receive_timestamp;
455 if (m_error_simulation_flag.get() == DONT_SEND)
457 ROS_DEBUG_STREAM(
"TestServerThread for command requests: error simulation, server not sending any telegrams");
460 if (m_error_simulation_flag.get() == SEND_RANDOM_TCP)
462 boost::system::error_code error_code;
463 std::vector<uint8_t> random_data = random_generator.
generate(random_length.
generate());
464 boost::asio::write(*p_socket, boost::asio::buffer(random_data.data(), random_data.size()), boost::asio::transfer_exactly(random_data.size()), error_code);
473 ROS_INFO_STREAM(
"TestServerThread: received cola request " << ascii_telegram);
477 if (m_error_simulation_flag.get() == SEND_INVALID_TELEGRAMS)
479 telegram_answer.command_name = random_ascii.
generate(random_length.
generate());
480 telegram_answer.parameter.clear();
481 for(
int n = random_length.
generate(); n > 0; n--)
482 telegram_answer.parameter.push_back(random_ascii.
generate(random_length.
generate()));
489 ROS_INFO_STREAM(
"TestServerThread: sending cola response " << ascii_response << (cola_binary ?
" (Cola-Binary)" :
" (Cola-ASCII)"));
493 ROS::Time send_timestamp;
498 if(iTransmitErrorCnt >= 10)
500 ROS_WARN_STREAM(
"## ERROR TestServerThread: " << iTransmitErrorCnt <<
" transmission errors, giving up.");
501 ROS_WARN_STREAM(
"## ERROR TestServerThread: shutdown after error, aborting");
507 iTransmitErrorCnt = 0;
513 m_tcp_send_scandata_thread_running =
true;
519 closeScandataThread();
524 closeScandataThread();
525 closeSocket(p_socket);
526 ROS_INFO_STREAM(
"TestServerThread: worker thread for command requests finished");
537 std::vector<sick_scan::JsonScanData> binary_messages;
538 ROS_INFO_STREAM(
"TestServerThread: worker thread sending scandata and scandatamon messages started.");
539 if(m_scandatafiles.empty())
541 ROS_WARN_STREAM(
"## WARNING TestServerThread::runWorkerThreadScandataCb(): no scandata files configured, aborting worker thread to send scandata.");
542 m_tcp_send_scandata_thread_running =
false;
545 if(ROS::ok() && m_tcp_send_scandata_thread_running)
551 for(
int n = 0; n < scandatafiles.size(); n++)
555 ROS_WARN_STREAM(
"## WARNING TestServerThread: error reading file \"" << scandatafiles[n] <<
"\".");
559 ROS_INFO_STREAM(
"TestServerThread: file \"" << scandatafiles[n] <<
"\" successfully parsed, " << binary_messages.size() <<
" messages of types \"" << m_scandatatypes <<
"\".");
564 if(binary_messages.empty())
566 ROS_WARN_STREAM(
"## WARNING TestServerThread::runWorkerThreadScandataCb(): no scandata found, aborting worker thread to send scandata.");
567 m_tcp_send_scandata_thread_running =
false;
571 double last_msg_timestamp = 0;
572 int iTransmitErrorCnt = 0;
573 for(
int msg_cnt = 0, msg_cnt_delta = 1; ROS::ok() && m_tcp_send_scandata_thread_running && p_socket; msg_cnt+=msg_cnt_delta)
575 if(msg_cnt >= (
int)binary_messages.size())
577 msg_cnt = (int)binary_messages.size() - 2;
582 msg_cnt = std::min(1, (
int)binary_messages.size() - 1);
589 ROS_INFO_STREAM(
"TestServerThread: sending " << binary_message.
data.size() <<
" byte scan data "
591 ROS::Time send_timestamp =
ROS::now();
596 if(iTransmitErrorCnt >= 10)
598 ROS_WARN_STREAM(
"## ERROR TestServerThread: " << iTransmitErrorCnt <<
" transmission errors, giving up.");
599 ROS_WARN_STREAM(
"## ERROR TestServerThread: shutdown after error, aborting");
605 iTransmitErrorCnt = 0;
607 last_msg_timestamp = binary_message.
timestamp;
610 m_tcp_send_scandata_thread_running =
false;
611 ROS_INFO_STREAM(
"TestServerThread: worker thread sending scandata and scandatamon messages finished.");
636 while(ROS::ok() && m_error_simulation_thread_running)
638 telegram_msg = m_last_telegram_received.get();
653 sick_scan::SickLocResultPortTelegramMsg telegram_msg;
654 size_t number_testcases = 0, number_testcases_failed = 0;
659 m_error_simulation_flag.set(
NO_ERROR);
660 ROS_INFO_STREAM(
"TestServerThread: 1. error simulation testcase: normal execution, expecting telegram messages from driver");
661 errorSimulationWait(10);
662 if(!errorSimulationWaitForTelegramReceived(10, telegram_msg))
664 number_testcases_failed++;
665 ROS_WARN_STREAM(
"## ERROR TestServerThread: 1. error simulation testcase: no ros telegram message received, expected SickLocResultPortTelegramMsg from driver");
672 m_error_simulation_flag.set(DONT_LISTEN);
673 ROS_INFO_STREAM(
"TestServerThread: 2. error simulation testcase: server not responding, not listening, no tcp connections accepted.");
674 m_worker_thread_running =
false;
676 closeTcpConnections(
true);
677 errorSimulationWait(10);
678 m_error_simulation_flag.set(
NO_ERROR);
679 ROS_INFO_STREAM(
"TestServerThread: 2. error simulation testcase: switched to normal execution, expecting telegram messages from driver");
680 errorSimulationWait(10);
681 if(!errorSimulationWaitForTelegramReceived(10, telegram_msg))
683 number_testcases_failed++;
684 ROS_WARN_STREAM(
"## ERROR TestServerThread: 2. error simulation testcase: no ros telegram message received, expected SickLocResultPortTelegramMsg from driver");
691 m_error_simulation_flag.set(DONT_ACCECPT);
692 ROS_INFO_STREAM(
"TestServerThread: 3. error simulation testcase: server not responding, listening on port " << m_ip_port_results <<
", but accepting no tcp clients");
693 m_worker_thread_running =
false;
695 closeTcpConnections(
true);
696 errorSimulationWait(10);
697 m_error_simulation_flag.set(
NO_ERROR);
698 errorSimulationWait(10);
699 if(!errorSimulationWaitForTelegramReceived(10, telegram_msg))
701 number_testcases_failed++;
702 ROS_WARN_STREAM(
"## ERROR TestServerThread: 3. error simulation testcase: no ros telegram message received, expected SickLocResultPortTelegramMsg from driver");
709 m_error_simulation_flag.set(DONT_SEND);
710 ROS_INFO_STREAM(
"TestServerThread: 4. error simulation testcase: server not sending telegrams");
711 errorSimulationWait(10);
712 m_error_simulation_flag.set(
NO_ERROR);
713 errorSimulationWait(10);
714 if(!errorSimulationWaitForTelegramReceived(10, telegram_msg))
716 number_testcases_failed++;
717 ROS_WARN_STREAM(
"## ERROR TestServerThread: 4. error simulation testcase: no ros telegram message received, expected SickLocResultPortTelegramMsg from driver");
724 m_error_simulation_flag.set(SEND_RANDOM_TCP);
725 ROS_INFO_STREAM(
"TestServerThread: 5. error simulation testcase: server sending random tcp data");
726 errorSimulationWait(10);
727 m_error_simulation_flag.set(
NO_ERROR);
728 errorSimulationWait(10);
729 if(!errorSimulationWaitForTelegramReceived(10, telegram_msg))
731 number_testcases_failed++;
732 ROS_WARN_STREAM(
"## ERROR TestServerThread: 5. error simulation testcase: no ros telegram message received, expected SickLocResultPortTelegramMsg from driver");
739 m_error_simulation_flag.set(SEND_INVALID_TELEGRAMS);
740 ROS_INFO_STREAM(
"TestServerThread: 6. error simulation testcase: server sending invalid telegrams");
741 errorSimulationWait(10);
742 m_error_simulation_flag.set(
NO_ERROR);
743 errorSimulationWait(10);
744 if(!errorSimulationWaitForTelegramReceived(10, telegram_msg))
746 number_testcases_failed++;
747 ROS_WARN_STREAM(
"## ERROR TestServerThread: 6. error simulation testcase: no ros telegram message received, expected SickLocResultPortTelegramMsg from driver");
753 m_error_simulation_thread_running =
false;
755 ROS_INFO_STREAM(
"TestServerThread: error simulation summary: " << (number_testcases - number_testcases_failed) <<
" of " << number_testcases<<
" testcases passed, " << number_testcases_failed <<
" failures.");