2020-12-26 14:12:05 -08:00
|
|
|
// Copyright (c) FIRST and other WPILib contributors.
|
|
|
|
|
// Open Source Software; you can modify and/or share it under the terms of
|
|
|
|
|
// the WPILib BSD license file in the root directory of this project.
|
2018-03-04 21:01:55 -08:00
|
|
|
|
|
|
|
|
#include "Telemetry.h"
|
|
|
|
|
|
|
|
|
|
#include <chrono>
|
2024-09-20 17:43:39 -07:00
|
|
|
#include <utility>
|
2018-03-04 21:01:55 -08:00
|
|
|
|
2018-04-29 23:33:19 -07:00
|
|
|
#include <wpi/DenseMap.h>
|
|
|
|
|
#include <wpi/timestamp.h>
|
2018-03-04 21:01:55 -08:00
|
|
|
|
|
|
|
|
#include "Handle.h"
|
2018-10-31 20:22:58 -07:00
|
|
|
#include "Instance.h"
|
2018-03-04 21:01:55 -08:00
|
|
|
#include "Notifier.h"
|
2018-10-31 20:22:58 -07:00
|
|
|
#include "SourceImpl.h"
|
2018-03-04 21:01:55 -08:00
|
|
|
|
|
|
|
|
using namespace cs;
|
|
|
|
|
|
|
|
|
|
class Telemetry::Thread : public wpi::SafeThread {
|
|
|
|
|
public:
|
2018-10-31 20:22:58 -07:00
|
|
|
explicit Thread(Notifier& notifier) : m_notifier(notifier) {}
|
|
|
|
|
|
2020-12-28 00:10:13 -08:00
|
|
|
void Main() override;
|
2018-03-04 21:01:55 -08:00
|
|
|
|
2018-10-31 20:22:58 -07:00
|
|
|
Notifier& m_notifier;
|
2018-04-29 23:33:19 -07:00
|
|
|
wpi::DenseMap<std::pair<CS_Handle, int>, int64_t> m_user;
|
|
|
|
|
wpi::DenseMap<std::pair<CS_Handle, int>, int64_t> m_current;
|
2018-03-04 21:01:55 -08:00
|
|
|
double m_period = 0.0;
|
|
|
|
|
double m_elapsed = 0.0;
|
|
|
|
|
bool m_updated = false;
|
|
|
|
|
int64_t GetValue(CS_Handle handle, CS_TelemetryKind kind, CS_Status* status);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int64_t Telemetry::Thread::GetValue(CS_Handle handle, CS_TelemetryKind kind,
|
|
|
|
|
CS_Status* status) {
|
|
|
|
|
auto it = m_user.find(std::make_pair(handle, static_cast<int>(kind)));
|
|
|
|
|
if (it == m_user.end()) {
|
|
|
|
|
*status = CS_EMPTY_VALUE;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return it->getSecond();
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-28 00:37:33 -08:00
|
|
|
Telemetry::~Telemetry() = default;
|
2018-03-04 21:01:55 -08:00
|
|
|
|
2020-12-28 12:58:06 -08:00
|
|
|
void Telemetry::Start() {
|
|
|
|
|
m_owner.Start(m_notifier);
|
|
|
|
|
}
|
2018-03-04 21:01:55 -08:00
|
|
|
|
2020-12-28 12:58:06 -08:00
|
|
|
void Telemetry::Stop() {
|
|
|
|
|
m_owner.Stop();
|
|
|
|
|
}
|
2018-03-04 21:01:55 -08:00
|
|
|
|
|
|
|
|
void Telemetry::Thread::Main() {
|
2019-07-07 19:17:14 -07:00
|
|
|
std::unique_lock lock(m_mutex);
|
2018-03-04 21:01:55 -08:00
|
|
|
auto prevTime = std::chrono::steady_clock::now();
|
|
|
|
|
while (m_active) {
|
|
|
|
|
double period = m_period;
|
2020-12-28 12:58:06 -08:00
|
|
|
if (period == 0) {
|
|
|
|
|
period = 1000.0;
|
|
|
|
|
}
|
2018-03-04 21:01:55 -08:00
|
|
|
auto timeoutTime = prevTime + std::chrono::duration<double>(period);
|
|
|
|
|
while (m_active && !m_updated) {
|
2020-12-28 12:58:06 -08:00
|
|
|
if (m_cond.wait_until(lock, timeoutTime) == std::cv_status::timeout) {
|
2018-03-04 21:01:55 -08:00
|
|
|
break;
|
2020-12-28 12:58:06 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!m_active) {
|
|
|
|
|
break;
|
2018-03-04 21:01:55 -08:00
|
|
|
}
|
|
|
|
|
if (m_updated) {
|
|
|
|
|
m_updated = false;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// move to user and clear current, as we don't keep around old values
|
|
|
|
|
m_user = std::move(m_current);
|
|
|
|
|
m_current.clear();
|
|
|
|
|
auto curTime = std::chrono::steady_clock::now();
|
|
|
|
|
m_elapsed = std::chrono::duration<double>(curTime - prevTime).count();
|
|
|
|
|
prevTime = curTime;
|
|
|
|
|
|
|
|
|
|
// notify
|
2018-10-31 20:22:58 -07:00
|
|
|
m_notifier.NotifyTelemetryUpdated();
|
2018-03-04 21:01:55 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Telemetry::SetPeriod(double seconds) {
|
|
|
|
|
auto thr = m_owner.GetThread();
|
2020-12-28 12:58:06 -08:00
|
|
|
if (!thr) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (thr->m_period == seconds) {
|
|
|
|
|
return; // no change
|
|
|
|
|
}
|
2018-03-04 21:01:55 -08:00
|
|
|
thr->m_period = seconds;
|
|
|
|
|
thr->m_updated = true;
|
|
|
|
|
thr->m_cond.notify_one();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double Telemetry::GetElapsedTime() {
|
|
|
|
|
auto thr = m_owner.GetThread();
|
2020-12-28 12:58:06 -08:00
|
|
|
if (!thr) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2018-03-04 21:01:55 -08:00
|
|
|
return thr->m_elapsed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64_t Telemetry::GetValue(CS_Handle handle, CS_TelemetryKind kind,
|
|
|
|
|
CS_Status* status) {
|
|
|
|
|
auto thr = m_owner.GetThread();
|
|
|
|
|
if (!thr) {
|
|
|
|
|
*status = CS_TELEMETRY_NOT_ENABLED;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return thr->GetValue(handle, kind, status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double Telemetry::GetAverageValue(CS_Handle handle, CS_TelemetryKind kind,
|
|
|
|
|
CS_Status* status) {
|
|
|
|
|
auto thr = m_owner.GetThread();
|
|
|
|
|
if (!thr) {
|
|
|
|
|
*status = CS_TELEMETRY_NOT_ENABLED;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2020-12-28 12:58:06 -08:00
|
|
|
if (thr->m_elapsed == 0) {
|
|
|
|
|
return 0.0;
|
|
|
|
|
}
|
2018-03-04 21:01:55 -08:00
|
|
|
return thr->GetValue(handle, kind, status) / thr->m_elapsed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Telemetry::RecordSourceBytes(const SourceImpl& source, int quantity) {
|
|
|
|
|
auto thr = m_owner.GetThread();
|
2020-12-28 12:58:06 -08:00
|
|
|
if (!thr) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-10-31 20:22:58 -07:00
|
|
|
auto handleData = Instance::GetInstance().FindSource(source);
|
2018-03-04 21:01:55 -08:00
|
|
|
thr->m_current[std::make_pair(Handle{handleData.first, Handle::kSource},
|
2018-03-07 01:14:21 -08:00
|
|
|
static_cast<int>(CS_SOURCE_BYTES_RECEIVED))] +=
|
|
|
|
|
quantity;
|
2018-03-04 21:01:55 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Telemetry::RecordSourceFrames(const SourceImpl& source, int quantity) {
|
|
|
|
|
auto thr = m_owner.GetThread();
|
2020-12-28 12:58:06 -08:00
|
|
|
if (!thr) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-10-31 20:22:58 -07:00
|
|
|
auto handleData = Instance::GetInstance().FindSource(source);
|
2018-03-04 21:01:55 -08:00
|
|
|
thr->m_current[std::make_pair(Handle{handleData.first, Handle::kSource},
|
2018-03-07 01:14:21 -08:00
|
|
|
static_cast<int>(CS_SOURCE_FRAMES_RECEIVED))] +=
|
|
|
|
|
quantity;
|
2018-03-04 21:01:55 -08:00
|
|
|
}
|