Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef SCIP2_RESPONSE_STREAM_H
00018 #define SCIP2_RESPONSE_STREAM_H
00019
00020 #include <boost/asio.hpp>
00021
00022 #include <map>
00023 #include <string>
00024 #include <vector>
00025
00026 #include <scip2/decode.h>
00027 #include <scip2/response/abstract.h>
00028
00029 namespace scip2
00030 {
00031 class ScanData
00032 {
00033 public:
00034 uint32_t timestamp_;
00035 std::vector<int32_t> ranges_;
00036 std::vector<int32_t> intensities_;
00037 };
00038
00039 class ResponseStream : public Response
00040 {
00041 public:
00042 using Callback = boost::function<void(
00043 const boost::posix_time::ptime &,
00044 const std::string &,
00045 const std::string &,
00046 const ScanData &)>;
00047
00048 protected:
00049 Callback cb_;
00050
00051 public:
00052 virtual std::string getCommandCode() const = 0;
00053 virtual void operator()(
00054 const boost::posix_time::ptime &,
00055 const std::string &,
00056 const std::string &,
00057 std::istream &) = 0;
00058
00059 bool readTimestamp(
00060 const boost::posix_time::ptime &time_read,
00061 const std::string &echo_back,
00062 const std::string &status,
00063 std::istream &stream,
00064 ScanData &scan)
00065 {
00066 if (status == "00")
00067 {
00068 return false;
00069 }
00070 if (status != "99")
00071 {
00072 if (cb_)
00073 cb_(time_read, echo_back, status, scan);
00074 std::cout << echo_back << " errored with " << status << std::endl;
00075 return false;
00076 }
00077 std::string stamp;
00078 if (!std::getline(stream, stamp))
00079 {
00080 std::cerr << "Failed to get timestamp" << std::endl;
00081 return false;
00082 }
00083 const uint8_t checksum = stamp.back();
00084 stamp.pop_back();
00085 if (stamp.size() < 4)
00086 {
00087 std::cerr << "Wrong timestamp format" << std::endl;
00088 return false;
00089 }
00090
00091 auto dec = Decoder<4>(stamp);
00092 auto it = dec.begin();
00093 scan.timestamp_ = *it;
00094 if ((dec.getChecksum() & 0x3F) + 0x30 != checksum)
00095 {
00096 std::cerr << "Checksum mismatch" << std::endl;
00097 return false;
00098 }
00099 return true;
00100 }
00101 void registerCallback(Callback cb)
00102 {
00103 cb_ = cb;
00104 }
00105 };
00106
00107 class ResponseMD : public ResponseStream
00108 {
00109 public:
00110 std::string getCommandCode() const
00111 {
00112 return std::string("MD");
00113 }
00114 void operator()(
00115 const boost::posix_time::ptime &time_read,
00116 const std::string &echo_back,
00117 const std::string &status,
00118 std::istream &stream) override
00119 {
00120 ScanData scan;
00121 if (!readTimestamp(time_read, echo_back, status, stream, scan))
00122 return;
00123 scan.ranges_.reserve(512);
00124
00125 std::string line;
00126 scip2::DecoderRemain remain;
00127 while (std::getline(stream, line))
00128 {
00129 if (line.size() == 0)
00130 break;
00131
00132 const uint8_t checksum = line.back();
00133 line.pop_back();
00134 if (line.size() < 3)
00135 {
00136 std::cerr << "Wrong stream format" << std::endl;
00137 return;
00138 }
00139 auto dec = Decoder<3>(line, remain);
00140 auto it = dec.begin();
00141 for (; it != dec.end(); ++it)
00142 {
00143 scan.ranges_.push_back(*it);
00144 }
00145 remain = it.getRemain();
00146 if ((dec.getChecksum() & 0x3F) + 0x30 != checksum)
00147 {
00148 std::cerr << "Checksum mismatch; scan dropped" << std::endl
00149 << line << std::endl;
00150 return;
00151 }
00152 }
00153 if (cb_)
00154 cb_(time_read, echo_back, status, scan);
00155 }
00156 };
00157
00158 class ResponseME : public ResponseStream
00159 {
00160 public:
00161 std::string getCommandCode() const
00162 {
00163 return std::string("ME");
00164 }
00165 void operator()(
00166 const boost::posix_time::ptime &time_read,
00167 const std::string &echo_back,
00168 const std::string &status,
00169 std::istream &stream) override
00170 {
00171 ScanData scan;
00172 if (!readTimestamp(time_read, echo_back, status, stream, scan))
00173 return;
00174 scan.ranges_.reserve(512);
00175 scan.intensities_.reserve(512);
00176
00177 std::string line;
00178 scip2::DecoderRemain remain;
00179 while (std::getline(stream, line))
00180 {
00181 if (line.size() == 0)
00182 break;
00183
00184 const uint8_t checksum = line.back();
00185 line.pop_back();
00186 if (line.size() < 3)
00187 {
00188 std::cerr << "Wrong stream format" << std::endl;
00189 return;
00190 }
00191 auto dec = Decoder<6>(line, remain);
00192 auto it = dec.begin();
00193 for (; it != dec.end(); ++it)
00194 {
00195 scan.ranges_.push_back((*it) >> 18);
00196 scan.intensities_.push_back((*it) & 0x3FFFF);
00197 }
00198 remain = it.getRemain();
00199 if ((dec.getChecksum() & 0x3F) + 0x30 != checksum)
00200 {
00201 std::cerr << "Checksum mismatch; scan dropped" << std::endl
00202 << line << std::endl;
00203 return;
00204 }
00205 }
00206 if (cb_)
00207 cb_(time_read, echo_back, status, scan);
00208 }
00209 };
00210
00211 }
00212
00213 #endif // SCIP2_RESPONSE_STREAM_H