|
|
@ -529,20 +529,38 @@ void ChartView::updateSeries(const Signal *sig, const std::vector<Event *> *even |
|
|
|
s.vals.reserve(settings.max_cached_minutes * 60 * 100); // [n]seconds * 100hz
|
|
|
|
s.vals.reserve(settings.max_cached_minutes * 60 * 100); // [n]seconds * 100hz
|
|
|
|
s.last_value_mono_time = 0; |
|
|
|
s.last_value_mono_time = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
double route_start_time = can->routeStartTime(); |
|
|
|
|
|
|
|
|
|
|
|
struct Chunk { |
|
|
|
|
|
|
|
std::vector<Event *>::const_iterator first, second; |
|
|
|
|
|
|
|
QVector<QPointF> vals; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
// split into one minitue chunks
|
|
|
|
|
|
|
|
QVector<Chunk> chunks; |
|
|
|
Event begin_event(cereal::Event::Which::INIT_DATA, s.last_value_mono_time); |
|
|
|
Event begin_event(cereal::Event::Which::INIT_DATA, s.last_value_mono_time); |
|
|
|
auto begin = std::upper_bound(events->begin(), events->end(), &begin_event, Event::lessThan()); |
|
|
|
auto begin = std::upper_bound(events->begin(), events->end(), &begin_event, Event::lessThan()); |
|
|
|
for (auto it = begin; it != events->end(); ++it) { |
|
|
|
for (auto it = begin, second = begin; it != events->end(); it = second) { |
|
|
|
if ((*it)->which == cereal::Event::Which::CAN) { |
|
|
|
second = std::lower_bound(it, events->end(), (*it)->mono_time + 1e9 * 60, [](auto &e, uint64_t ts) { return e->mono_time < ts; }); |
|
|
|
for (const auto &c : (*it)->event.getCan()) { |
|
|
|
chunks.push_back({it, second}); |
|
|
|
if (s.address == c.getAddress() && s.source == c.getSrc()) { |
|
|
|
} |
|
|
|
auto dat = c.getDat(); |
|
|
|
|
|
|
|
double value = get_raw_value((uint8_t *)dat.begin(), dat.size(), *s.sig); |
|
|
|
QtConcurrent::blockingMap(chunks, [&](Chunk &chunk) { |
|
|
|
double ts = ((*it)->mono_time / (double)1e9) - route_start_time; // seconds
|
|
|
|
chunk.vals.reserve(60 * 100); // 100 hz
|
|
|
|
s.vals.push_back({ts, value}); |
|
|
|
double route_start_time = can->routeStartTime(); |
|
|
|
|
|
|
|
for (auto it = chunk.first; it != chunk.second; ++it) { |
|
|
|
|
|
|
|
if ((*it)->which == cereal::Event::Which::CAN) { |
|
|
|
|
|
|
|
for (const auto &c : (*it)->event.getCan()) { |
|
|
|
|
|
|
|
if (s.address == c.getAddress() && s.source == c.getSrc()) { |
|
|
|
|
|
|
|
auto dat = c.getDat(); |
|
|
|
|
|
|
|
double value = get_raw_value((uint8_t *)dat.begin(), dat.size(), *s.sig); |
|
|
|
|
|
|
|
double ts = ((*it)->mono_time / (double)1e9) - route_start_time; // seconds
|
|
|
|
|
|
|
|
chunk.vals.push_back({ts, value}); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
for (auto &c : chunks) { |
|
|
|
|
|
|
|
s.vals.append(c.vals); |
|
|
|
} |
|
|
|
} |
|
|
|
if (events->size()) { |
|
|
|
if (events->size()) { |
|
|
|
s.last_value_mono_time = events->back()->mono_time; |
|
|
|
s.last_value_mono_time = events->back()->mono_time; |
|
|
|