21 std::ifstream file(filename, std::ifstream::in);
24 throw std::runtime_error(
"ULog: Failed to open replay file");
27 file.seekg(0, std::ios::end);
28 long length = file.tellg();
29 file.seekg(0, std::ios::beg);
31 datastream.
data.resize(length);
32 file.read( &datastream.
data[0], length);
39 throw std::runtime_error(
"ULog: wrong header");
44 throw std::runtime_error(
"ULog: error loading definitions");
57 message[message_header.
msg_size] =
'\0';
64 sub.
multi_id = *
reinterpret_cast<uint8_t*
>(message);
65 sub.
msg_id = *
reinterpret_cast<uint16_t*
>(message + 1);
86 printf(
"REMOVE_LOGGED_MSG\n");
88 uint16_t msg_id = *
reinterpret_cast<uint16_t*
>(message);
93 uint16_t msg_id = *
reinterpret_cast<uint16_t*
>(message);
108 msg.
level =
static_cast<char>(message[0]);
109 message +=
sizeof(char);
110 msg.
timestamp = *
reinterpret_cast<uint64_t*
>(message);
111 message +=
sizeof(uint64_t);
112 msg.
msg.assign(message, message_header.
msg_size - 9);
126 printf(
"PARAMETER changed at run-time. Ignored\n");
127 std::cout << std::flush;
135 size_t other_fields_count = 0;
142 other_fields_count++;
149 sprintf(buff,
".%02d", sub.
multi_id);
150 ts_name += std::string(buff);
161 uint64_t time_val = *
reinterpret_cast<uint64_t*
>(message);
163 message +=
sizeof(uint64_t);
176 message +=
field.array_size;
180 for (
int array_pos = 0; array_pos <
field.array_size; array_pos++)
186 value =
static_cast<double>(*
reinterpret_cast<uint8_t*
>(message));
191 value =
static_cast<double>(*
reinterpret_cast<int8_t*
>(message));
196 value =
static_cast<double>(*
reinterpret_cast<uint16_t*
>(message));
201 value =
static_cast<double>(*
reinterpret_cast<int16_t*
>(message));
206 value =
static_cast<double>(*
reinterpret_cast<uint32_t*
>(message));
211 value =
static_cast<double>(*
reinterpret_cast<int32_t*
>(message));
216 value =
static_cast<double>(*
reinterpret_cast<uint64_t*
>(message));
221 value =
static_cast<double>(*
reinterpret_cast<int64_t*
>(message));
226 value =
static_cast<double>(*
reinterpret_cast<float*
>(message));
231 value = (*
reinterpret_cast<double*
>(message));
236 value =
static_cast<double>(*
reinterpret_cast<char*
>(message));
241 value =
static_cast<double>(*
reinterpret_cast<bool*
>(message));
248 message +=
sizeof(uint64_t);
257 timeseries.
data[(*index)++].second.push_back(value);
289 datastream.
read(message, msg_size);
290 message[msg_size] = 0;
312 count += size_t(
field.array_size);
320 std::vector<StringView> splitted_strings;
321 splitted_strings.reserve(4);
324 while (pos < strToSplit.size())
326 size_t new_pos = strToSplit.find_first_of(delimeter, pos);
327 if (new_pos == std::string::npos)
329 new_pos = strToSplit.size();
331 StringView sv = { &strToSplit.data()[pos], new_pos - pos };
332 splitted_strings.push_back(sv);
335 return splitted_strings;
341 datastream.
read((
char*)&msg_header,
sizeof(msg_header));
359 return memcmp(magic, msg_header.
magic, 7) == 0;
368 qDebug() <<
"\n" << datastream.
offset;
370 qDebug() << message_header.
msg_size;
371 qDebug() << datastream.
offset;
420 printf(
"unknown log definition type %i, size %i (offset %i)",
435 printf(
"unsupported message length for FLAG_BITS message (%i)", msg_size);
441 datastream.
read((
char*)message, msg_size);
444 uint8_t* incompat_flags = message + 8;
448 bool has_unknown_incompat_bits =
false;
450 if (incompat_flags[0] & ~0x1)
452 has_unknown_incompat_bits =
true;
455 for (
int i = 1; i < 8; ++i)
457 if (incompat_flags[i])
459 has_unknown_incompat_bits =
true;
463 if (has_unknown_incompat_bits)
465 printf(
"Log contains unknown incompat bits set. Refusing to parse");
469 if (contains_appended_data)
471 uint64_t appended_offsets[3];
472 memcpy(appended_offsets, message + 16,
sizeof(appended_offsets));
474 if (appended_offsets[0] > 0)
486 static int count = 0;
490 datastream.
read(buffer, msg_size);
491 buffer[msg_size] = 0;
499 size_t pos = str_format.find(
':');
501 if (pos == std::string::npos)
506 std::string
name = str_format.substr(0, pos);
507 std::string fields = str_format.substr(pos + 1);
511 format.
fields.reserve(fields_split.size());
512 for (
auto field_section : fields_split)
515 auto field_type = field_pair.at(0);
516 auto field_name = field_pair.at(1);
519 if (field_type.starts_with(
"int8_t"))
522 field_type.remove_prefix(6);
524 else if (field_type.starts_with(
"int16_t"))
527 field_type.remove_prefix(7);
529 else if (field_type.starts_with(
"int32_t"))
532 field_type.remove_prefix(7);
534 else if (field_type.starts_with(
"int64_t"))
537 field_type.remove_prefix(7);
539 else if (field_type.starts_with(
"uint8_t"))
542 field_type.remove_prefix(7);
544 else if (field_type.starts_with(
"uint16_t"))
547 field_type.remove_prefix(8);
549 else if (field_type.starts_with(
"uint32_t"))
552 field_type.remove_prefix(8);
554 else if (field_type.starts_with(
"uint64_t"))
557 field_type.remove_prefix(8);
559 else if (field_type.starts_with(
"double"))
562 field_type.remove_prefix(6);
564 else if (field_type.starts_with(
"float"))
567 field_type.remove_prefix(5);
569 else if (field_type.starts_with(
"bool"))
572 field_type.remove_prefix(4);
574 else if (field_type.starts_with(
"char"))
577 field_type.remove_prefix(4);
583 if (field_type.ends_with(
"]"))
586 while (!helper.ends_with(
"["))
588 helper.remove_suffix(1);
591 helper.remove_suffix(1);
594 while (!field_type.starts_with(
"["))
596 field_type.remove_prefix(1);
607 if (field_type.size() > 0 && field_type[0] ==
'[')
609 field_type.remove_prefix(1);
611 field_type.remove_prefix(1);
613 while (field_type[0] !=
']')
616 field_type.remove_prefix(1);
627 format.
fields.push_back(field);
637 template <
typename T>
640 std::stringstream stream;
641 stream <<
"0x" << std::setfill(
'0') << std::setw(
sizeof(T) * 2) << std::hex << i;
649 datastream.
read((
char*)message, msg_size);
655 uint8_t key_len = message[0];
657 std::string raw_key((
char*)message, key_len);
662 std::string key = key_parts[1].to_string();
665 if (key_parts[0].starts_with(
"char["))
667 value = std::string((
char*)message, msg_size - key_len - 1);
671 bool val = *
reinterpret_cast<const bool*
>(key_parts[0].data());
672 value = std::to_string(val);
674 else if (key_parts[0] ==
StringView(
"uint8_t"))
676 uint8_t val = *
reinterpret_cast<const uint8_t*
>(key_parts[0].data());
677 value = std::to_string(val);
679 else if (key_parts[0] ==
StringView(
"int8_t"))
681 int8_t val = *
reinterpret_cast<const int8_t*
>(key_parts[0].data());
682 value = std::to_string(val);
684 else if (key_parts[0] ==
StringView(
"uint16_t"))
686 uint16_t val = *
reinterpret_cast<const uint16_t*
>(key_parts[0].data());
687 value = std::to_string(val);
689 else if (key_parts[0] ==
StringView(
"int16_t"))
691 int16_t val = *
reinterpret_cast<const int16_t*
>(key_parts[0].data());
692 value = std::to_string(val);
694 else if (key_parts[0] ==
StringView(
"uint32_t"))
696 uint32_t val = *
reinterpret_cast<const uint32_t*
>(key_parts[0].data());
697 if (key_parts[1].starts_with(
"ver_") && key_parts[1].ends_with(
"_release"))
703 value = std::to_string(val);
706 else if (key_parts[0] ==
StringView(
"int32_t"))
708 int32_t val = *
reinterpret_cast<const int32_t*
>(key_parts[0].data());
709 value = std::to_string(val);
713 float val = *
reinterpret_cast<const float*
>(key_parts[0].data());
714 value = std::to_string(val);
716 else if (key_parts[0] ==
StringView(
"double"))
718 double val = *
reinterpret_cast<const double*
>(key_parts[0].data());
719 value = std::to_string(val);
721 else if (key_parts[0] ==
StringView(
"uint64_t"))
723 uint64_t val = *
reinterpret_cast<const uint64_t*
>(key_parts[0].data());
724 value = std::to_string(val);
726 else if (key_parts[0] ==
StringView(
"int64_t"))
728 int64_t val = *
reinterpret_cast<const int64_t*
>(key_parts[0].data());
729 value = std::to_string(val);
732 _info.insert({ key, value });
740 datastream.
read((
char*)message, msg_size);
747 uint8_t key_len = message[0];
748 std::string key((
char*)message + 1, key_len);
750 size_t pos = key.find(
' ');
752 if (pos == std::string::npos)
757 std::string
type = key.substr(0, pos);
760 param.
name = key.substr(pos + 1);
762 if (type ==
"int32_t")
764 param.
value.
val_int = *
reinterpret_cast<int32_t*
>(message + 1 + key_len);
767 else if (type ==
"float")
769 param.
value.
val_real = *
reinterpret_cast<float*
>(message + 1 + key_len);
774 throw std::runtime_error(
"unknown parameter type");
782 std::function<void(const Format& format, const std::string& prefix)> appendVector;
786 appendVector = [&appendVector,
this, ×eries](
const Format&
format,
const std::string& prefix) {
787 for (
const auto&
field : format.fields)
795 std::string new_prefix = prefix +
"/" +
field.field_name;
796 for (
int i = 0; i <
field.array_size; i++)
798 std::string array_suffix =
"";
799 if (
field.array_size > 1)
802 sprintf(buff,
".%02d", i);
807 timeseries.
data.push_back({ new_prefix + array_suffix, std::vector<double>() });
811 appendVector(this->
_formats.at(
field.other_type_ID), new_prefix + array_suffix);
817 appendVector(*format, {});
std::vector< uint64_t > timestamps
const std::vector< MessageLog > & getLogs() const
static int str_format(lua_State *L)
enum MQTTPropertyCodes value
Timeseries createTimeseries(const Format *format)
FMT_INLINE std::basic_string< Char > format(const S &format_str, Args &&...args)
std::vector< MessageLog > _message_logs
std::streampos _data_section_start
first ADD_LOGGED_MSG message
#define ULOG_INCOMPAT_FLAG0_DATA_APPENDED_MASK
bool readParameter(DataStream &datastream, uint16_t msg_size)
uint64_t _file_start_time
std::vector< Parameter > _parameters
std::map< std::string, Timeseries > _timeseries
nonstd::string_view StringView
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
const std::map< std::string, Timeseries > & getTimeseriesMap() const
ULogParser(const std::string &filename)
size_t fieldsCount(const Format &format) const
std::map< std::string, std::string > _info
static void field(LexState *ls, ConsControl *cc)
const T & move(const T &v)
const std::vector< Parameter > & getParameters() const
#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)
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
union ULogParser::Parameter::@102 value
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)
const std::map< std::string, std::string > & getInfo() const
std::string other_type_ID