26 #include <boost/asio/error.hpp>
27 #include <boost/asio/ip/tcp.hpp>
28 #include <boost/asio/placeholders.hpp>
29 #include <boost/asio/read_until.hpp>
30 #include <boost/asio/write.hpp>
31 #include <boost/bind/bind.hpp>
32 #include <boost/date_time/posix_time/posix_time.hpp>
33 #include <boost/move/move.hpp>
34 #include <boost/system/error_code.hpp>
45 const char* status_ok =
"00";
46 const char* status_already =
"02";
47 const char* status_error_command_not_defined =
"0E";
48 const char* status_error_abnormal =
"0L";
49 const char* status_error_denied =
"10";
50 const char* status_error_command_short =
"0C";
51 const char* status_error_command_long =
"0D";
56 boost::asio::async_read_until(
66 std::cerr <<
"Connection closed: " << ec.message() << std::endl;
70 const auto now = boost::posix_time::microsec_clock::universal_time();
71 const auto delay = boost::posix_time::microseconds(
73 const auto when = now + delay;
77 while (std::getline(stream, line))
86 const std::string cmd,
87 const boost::posix_time::ptime& when)
90 const std::string op = cmd.substr(0, 2);
98 wait.expires_at(when);
120 std::stringstream ss;
121 ss << std::setfill(
'0') << std::setw(6) << std::hex << stamp;
136 std::lock_guard<std::mutex> lock(
mu_);
144 mesm =
"001 Booting";
147 mesm =
"003 Single_scan";
150 mesm =
"004 Multi_scan";
156 stat =
"Stable 000 no error.";
160 mesm =
"Measuring by Sensitive Mode";
161 stat =
"sensor is working normally";
180 {
"SCSP", std::to_string(rpm)},
182 {
"SBPS",
"Ethernet 100 [Mbps]"},
197 {
"VEND",
"Hokuyo Automatic Co., Ltd."},
200 {
"PROT",
"SCIP 2.2"},
201 {
"SERI",
"H0123456"},
220 {
"PROT",
"SCIP 2.2"},
225 {
"SCAN", std::to_string(rpm)},
237 std::lock_guard<std::mutex> lock(
mu_);
241 response(cmd, status_error_abnormal);
304 std::lock_guard<std::mutex> lock(
mu_);
309 response(cmd, status_error_abnormal);
332 std::lock_guard<std::mutex> lock(
mu_);
337 response(cmd, status_error_abnormal);
361 std::lock_guard<std::mutex> lock(
mu_);
365 response(cmd, status_error_abnormal);
384 const auto now = boost::posix_time::microsec_clock::universal_time();
385 if (
last_rb_ == boost::posix_time::not_a_date_time ||
386 now -
last_rb_ > boost::posix_time::seconds(1))
394 boot_timer_.expires_from_now(boost::posix_time::seconds(1));
408 std::lock_guard<std::mutex> lock(
mu_);
418 catch (
const std::invalid_argument& e)
462 response(cmd, status_error_command_not_defined);
467 std::lock_guard<std::mutex> lock(
mu_);
480 std::cerr <<
"Booting" << std::endl;
482 std::lock_guard<std::mutex> lock(
mu_);
491 const auto delay = boost::posix_time::microseconds(
502 std::cerr <<
"Closing" << std::endl;
510 std::cerr <<
"Booted" << std::endl;
512 std::lock_guard<std::mutex> lock(
mu_);
527 next_scan_ = boost::posix_time::microsec_clock::universal_time();
532 const std::string echo,
533 const std::string status,
534 const std::string data)
536 const auto now = boost::posix_time::microsec_clock::universal_time();
537 const auto delay = boost::posix_time::microseconds(
539 const auto when = now + delay;
541 const std::string text =
550 const std::string echo,
551 const std::string status,
552 const std::vector<std::pair<std::string, std::string>> kvs)
554 std::stringstream ss;
555 for (
const auto& kv : kvs)
557 const std::string line = kv.first +
":" + kv.second;
564 const std::string data,
565 const boost::posix_time::ptime& when)
568 wait.expires_at(when);
571 boost::system::error_code ec;
572 boost::asio::write(
socket_, boost::asio::buffer(data), ec);
575 std::cerr <<
"Send failed: " << ec.message() << std::endl;
583 return diff & 0xFFFFFF;
588 std::cerr <<
"Accepting" << std::endl;
598 const boost::system::error_code& ec)
602 std::cerr <<
"Failed to accept: " << ec.message() << std::endl;
606 std::cerr <<
"Accepted connection from "
607 <<
socket_.remote_endpoint() << std::endl;
608 socket_.set_option(boost::asio::ip::tcp::no_delay(
true));
611 std::lock_guard<std::mutex> lock(
mu_);
624 boost::posix_time::microseconds(
636 std::lock_guard<std::mutex> lock(
mu_);
658 raw_scan->ranges.resize(num_points);
659 raw_scan->intensities.resize(num_points);
663 const double busy_seconds =
667 boost::asio::deadline_timer scan_wait(
io_service_);
668 scan_wait.expires_at(
670 boost::posix_time::microseconds(
671 static_cast<int64_t
>(busy_seconds * 1e6)));
675 std::lock_guard<std::mutex> lock(
mu_);
704 std::vector<uint32_t> data;
714 std::stringstream ss;
722 for (
size_t i = 0; i < encoded.size(); i += 64)
724 const std::string line = encoded.substr(i, 64);
728 std::stringstream ss_echo;
737 << std::setfill(
'0') << std::setw(2)
755 response(ss_echo.str(),
"99", ss.str());
759 const std::string& cmd,
760 const size_t expected_size)
762 if (cmd.size() < expected_size)
764 response(cmd, status_error_command_short);
767 if (cmd.size() == expected_size)
771 if (cmd[expected_size] !=
';')
773 response(cmd, status_error_command_long);
783 std::thread th_input_queue(
785 std::thread th_output_queue(
793 th_input_queue.join();
794 th_output_queue.join();
799 boost::asio::deadline_timer keepalive_timer(
fifo);
800 std::function<void(
const boost::system::error_code& ec)> keepalive;
802 keepalive = [&keepalive_timer, &keepalive](
const boost::system::error_code& ec)
804 if (ec == boost::asio::error::operation_aborted)
810 std::cerr <<
"fifo keepalive error: " << ec << std::endl;
813 keepalive_timer.expires_from_now(boost::posix_time::hours(1));
814 keepalive_timer.async_wait(keepalive);
819 keepalive(boost::system::error_code());
835 std::lock_guard<std::mutex> lock(
mu_);
841 std::lock_guard<std::mutex> lock(
mu_);
853 const auto now = boost::posix_time::microsec_clock::universal_time();
854 const double tick_ms = 1000 * n;
855 const uint64_t next_tick =
857 const auto next_tick_system_microseconds =
861 timestamp_epoch_ + boost::posix_time::microseconds(next_tick_system_microseconds));