19 throw std::runtime_error(
"ULog: wrong header");
24 throw std::runtime_error(
"ULog: error loading definitions");
36 datastream.
read(message, message_header.msg_size);
37 message[message_header.msg_size] =
'\0';
39 switch (message_header.msg_type)
44 sub.
multi_id = *
reinterpret_cast<uint8_t*
>(message);
45 sub.
msg_id = *
reinterpret_cast<uint16_t*
>(message + 1);
47 sub.
message_name.assign(message, message_header.msg_size - 3);
66 printf(
"REMOVE_LOGGED_MSG\n");
68 uint16_t msg_id = *
reinterpret_cast<uint16_t*
>(message);
73 uint16_t msg_id = *
reinterpret_cast<uint16_t*
>(message);
88 msg.
level =
static_cast<char>(message[0]);
89 message +=
sizeof(char);
90 msg.
timestamp = *
reinterpret_cast<uint64_t*
>(message);
91 message +=
sizeof(uint64_t);
92 msg.
msg.assign(message, message_header.msg_size - 9);
108 printf(
"PARAMETER changed at run-time. Ignored\n");
109 std::cout << std::flush;
117 size_t other_fields_count = 0;
124 other_fields_count++;
132 ts_name += std::string(buff);
143 uint64_t time_val = *
reinterpret_cast<uint64_t*
>(message);
145 message +=
sizeof(uint64_t);
152 char* message,
size_t*
index)
159 message +=
field.array_size;
163 for (
int array_pos = 0; array_pos <
field.array_size; array_pos++)
169 value =
static_cast<double>(*
reinterpret_cast<uint8_t*
>(message));
174 value =
static_cast<double>(*
reinterpret_cast<int8_t*
>(message));
179 value =
static_cast<double>(*
reinterpret_cast<uint16_t*
>(message));
184 value =
static_cast<double>(*
reinterpret_cast<int16_t*
>(message));
189 value =
static_cast<double>(*
reinterpret_cast<uint32_t*
>(message));
194 value =
static_cast<double>(*
reinterpret_cast<int32_t*
>(message));
199 value =
static_cast<double>(*
reinterpret_cast<uint64_t*
>(message));
204 value =
static_cast<double>(*
reinterpret_cast<int64_t*
>(message));
209 value =
static_cast<double>(*
reinterpret_cast<float*
>(message));
214 value = (*
reinterpret_cast<double*
>(message));
219 value =
static_cast<double>(*
reinterpret_cast<char*
>(message));
224 value =
static_cast<double>(*
reinterpret_cast<bool*
>(message));
231 message +=
sizeof(uint64_t);
240 timeseries.
data[(*index)++].second.push_back(value);
272 datastream.
read(message, msg_size);
273 message[msg_size] = 0;
304 std::vector<StringView> splitted_strings;
305 splitted_strings.reserve(4);
308 while (pos < strToSplit.size())
310 size_t new_pos = strToSplit.find_first_of(delimeter, pos);
311 if (new_pos == std::string::npos)
313 new_pos = strToSplit.size();
315 StringView sv = { &strToSplit.data()[pos], new_pos - pos };
316 splitted_strings.push_back(sv);
319 return splitted_strings;
325 datastream.
read((
char*)&msg_header,
sizeof(msg_header));
343 return memcmp(magic, msg_header.magic, 7) == 0;
363 switch (message_header.msg_type)
373 if (!
readFormat(datastream, message_header.msg_size))
394 if (!
readInfo(datastream, message_header.msg_size))
402 datastream.
offset += message_header.msg_size;
406 printf(
"unknown log definition type %i, size %i (offset %i)\n",
407 (
int)message_header.msg_type, (
int)message_header.msg_size,
409 datastream.
offset += message_header.msg_size;
420 printf(
"unsupported message length for FLAG_BITS message (%i)", msg_size);
426 datastream.
read((
char*)message, msg_size);
429 uint8_t* incompat_flags = message + 8;
432 bool contains_appended_data =
434 bool has_unknown_incompat_bits =
false;
436 if (incompat_flags[0] & ~0x1)
438 has_unknown_incompat_bits =
true;
441 for (
int i = 1; i < 8; ++i)
443 if (incompat_flags[i])
445 has_unknown_incompat_bits =
true;
449 if (has_unknown_incompat_bits)
451 printf(
"Log contains unknown incompat bits set. Refusing to parse");
455 if (contains_appended_data)
457 uint64_t appended_offsets[3];
458 memcpy(appended_offsets, message + 16,
sizeof(appended_offsets));
460 if (appended_offsets[0] > 0)
473 static int count = 0;
477 datastream.
read(buffer, msg_size);
478 buffer[msg_size] = 0;
486 size_t pos = str_format.find(
':');
488 if (pos == std::string::npos)
493 std::string
name = str_format.substr(0, pos);
494 std::string fields = str_format.substr(pos + 1);
498 format.
fields.reserve(fields_split.size());
499 for (
auto field_section : fields_split)
503 auto field_name = field_pair.at(1);
573 while (!helper.ends_with(
"["))
575 helper.remove_suffix(1);
578 helper.remove_suffix(1);
614 format.
fields.push_back(field);
624 template <
typename T>
627 std::stringstream stream;
628 stream <<
"0x" << std::setfill(
'0') << std::setw(
sizeof(T) * 2) << std::hex << i;
636 datastream.
read((
char*)message, msg_size);
642 uint8_t key_len = message[0];
644 std::string raw_key((
char*)message, key_len);
649 std::string key = key_parts[1].to_string();
652 if (key_parts[0].starts_with(
"char["))
654 value = std::string((
char*)message, msg_size - key_len - 1);
658 bool val = *
reinterpret_cast<const bool*
>(key_parts[0].data());
659 value = std::to_string(val);
661 else if (key_parts[0] ==
StringView(
"uint8_t"))
663 uint8_t val = *
reinterpret_cast<const uint8_t*
>(key_parts[0].data());
664 value = std::to_string(val);
666 else if (key_parts[0] ==
StringView(
"int8_t"))
668 int8_t val = *
reinterpret_cast<const int8_t*
>(key_parts[0].data());
669 value = std::to_string(val);
671 else if (key_parts[0] ==
StringView(
"uint16_t"))
673 uint16_t val = *
reinterpret_cast<const uint16_t*
>(key_parts[0].data());
674 value = std::to_string(val);
676 else if (key_parts[0] ==
StringView(
"int16_t"))
678 int16_t val = *
reinterpret_cast<const int16_t*
>(key_parts[0].data());
679 value = std::to_string(val);
681 else if (key_parts[0] ==
StringView(
"uint32_t"))
683 uint32_t val = *
reinterpret_cast<const uint32_t*
>(key_parts[0].data());
684 if (key_parts[1].starts_with(
"ver_") && key_parts[1].ends_with(
"_release"))
690 value = std::to_string(val);
693 else if (key_parts[0] ==
StringView(
"int32_t"))
695 int32_t val = *
reinterpret_cast<const int32_t*
>(key_parts[0].data());
696 value = std::to_string(val);
700 float val = *
reinterpret_cast<const float*
>(key_parts[0].data());
701 value = std::to_string(val);
703 else if (key_parts[0] ==
StringView(
"double"))
705 double val = *
reinterpret_cast<const double*
>(key_parts[0].data());
706 value = std::to_string(val);
708 else if (key_parts[0] ==
StringView(
"uint64_t"))
710 uint64_t val = *
reinterpret_cast<const uint64_t*
>(key_parts[0].data());
711 value = std::to_string(val);
713 else if (key_parts[0] ==
StringView(
"int64_t"))
715 int64_t val = *
reinterpret_cast<const int64_t*
>(key_parts[0].data());
716 value = std::to_string(val);
719 _info.insert({ key, value });
727 datastream.
read((
char*)message, msg_size);
734 uint8_t key_len = message[0];
735 std::string key((
char*)message + 1, key_len);
737 size_t pos = key.find(
' ');
739 if (pos == std::string::npos)
744 std::string
type = key.substr(0, pos);
747 param.
name = key.substr(pos + 1);
749 if (type ==
"int32_t")
751 param.
value.
val_int = *
reinterpret_cast<int32_t*
>(message + 1 + key_len);
754 else if (type ==
"float")
756 param.
value.
val_real = *
reinterpret_cast<float*
>(message + 1 + key_len);
761 throw std::runtime_error(
"unknown parameter type");
769 std::function<void(const Format& format, const std::string& prefix)> appendVector;
773 appendVector = [&appendVector,
this, ×eries](
const Format&
format,
774 const std::string& prefix) {
775 for (
const auto&
field : format.fields)
783 std::string new_prefix = prefix +
"/" +
field.field_name;
784 for (
int i = 0; i <
field.array_size; i++)
786 std::string array_suffix =
"";
787 if (
field.array_size > 1)
795 timeseries.
data.push_back({ new_prefix + array_suffix, std::vector<double>() });
799 appendVector(this->
_formats.at(
field.other_type_ID), new_prefix + array_suffix);
805 appendVector(*format, {});
std::vector< uint64_t > timestamps
static int str_format(lua_State *L)
Timeseries createTimeseries(const Format *format)
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val)
std::vector< MessageLog > _message_logs
const std::map< std::string, std::string > & getInfo() const
std::streampos _data_section_start
first ADD_LOGGED_MSG message
size_t fieldsCount(const Format &format) const
auto printf(const S &fmt, const T &... args) -> int
span_CONFIG_SIZE_TYPE size_t
#define ULOG_INCOMPAT_FLAG0_DATA_APPENDED_MASK
const std::map< std::string, Timeseries > & getTimeseriesMap() const
bool readParameter(DataStream &datastream, uint16_t msg_size)
uint64_t _file_start_time
std::vector< Parameter > _parameters
union ULogParser::Parameter::@52 value
std::map< std::string, Timeseries > _timeseries
auto sprintf(const S &fmt, const T &... args) -> std::basic_string< Char >
nonstd::string_view StringView
const std::vector< Parameter > & getParameters() const
std::vector< StringView > splitString(const StringView &strToSplit, char delimeter)
bool readSubscription(DataStream &datastream, uint16_t msg_size)
std::string int_to_hex(T i)
int64_t _read_until_file_position
read limit if log contains appended data
constexpr auto count() -> size_t
std::map< std::string, std::string > _info
static void field(LexState *ls, ConsControl *cc)
const std::vector< MessageLog > & getLogs() const
const T & move(const T &v)
const T & first(const T &value, const Tail &...)
#define ULOG_MSG_HEADER_LEN
std::vector< uint8_t > _read_buffer
std::set< std::string > _message_name_with_multi_id
void read(char *dst, int len)
ULogParser(DataStream &datastream)
char * parseSimpleDataMessage(Timeseries ×eries, const Format *format, char *message, size_t *index)
bool readInfo(DataStream &datastream, uint16_t msg_size)
bool readFormat(DataStream &datastream, uint16_t msg_size)
std::map< std::string, Format > _formats
std::vector< std::pair< std::string, std::vector< double > > > data
void parseDataMessage(const Subscription &sub, char *message)
std::map< uint16_t, Subscription > _subscriptions
bool readFlagBits(DataStream &datastream, uint16_t msg_size)
bool readFileHeader(DataStream &datastream)
bool readFileDefinitions(DataStream &datastream)
std::basic_string< Char > format(const text_style &ts, const S &format_str, const Args &... args)
std::string other_type_ID