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.
|
2016-01-02 03:02:34 -08:00
|
|
|
|
2018-07-20 00:03:45 -07:00
|
|
|
#include "frc/livewindow/LiveWindow.h"
|
2016-09-25 16:50:13 -07:00
|
|
|
|
2017-12-07 23:34:29 -08:00
|
|
|
#include <networktables/NetworkTable.h>
|
|
|
|
|
#include <networktables/NetworkTableEntry.h>
|
|
|
|
|
#include <networktables/NetworkTableInstance.h>
|
2018-04-29 23:33:19 -07:00
|
|
|
#include <wpi/mutex.h>
|
2017-08-27 00:11:52 -07:00
|
|
|
|
2019-11-01 21:58:54 -07:00
|
|
|
#include "frc/smartdashboard/Sendable.h"
|
2018-07-20 00:03:45 -07:00
|
|
|
#include "frc/smartdashboard/SendableBuilderImpl.h"
|
2019-09-14 15:22:54 -05:00
|
|
|
#include "frc/smartdashboard/SendableRegistry.h"
|
2013-12-15 18:30:16 -05:00
|
|
|
|
2016-11-01 22:33:12 -07:00
|
|
|
using namespace frc;
|
|
|
|
|
|
2018-04-29 23:33:19 -07:00
|
|
|
using wpi::Twine;
|
2017-12-04 23:28:33 -08:00
|
|
|
|
|
|
|
|
struct LiveWindow::Impl {
|
|
|
|
|
Impl();
|
|
|
|
|
|
|
|
|
|
struct Component {
|
|
|
|
|
bool firstTime = true;
|
|
|
|
|
bool telemetryEnabled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
wpi::mutex mutex;
|
|
|
|
|
|
2019-09-14 15:22:54 -05:00
|
|
|
SendableRegistry& registry;
|
|
|
|
|
int dataHandle;
|
2017-12-04 23:28:33 -08:00
|
|
|
|
|
|
|
|
std::shared_ptr<nt::NetworkTable> liveWindowTable;
|
|
|
|
|
std::shared_ptr<nt::NetworkTable> statusTable;
|
|
|
|
|
nt::NetworkTableEntry enabledEntry;
|
|
|
|
|
|
|
|
|
|
bool startLiveWindow = false;
|
|
|
|
|
bool liveWindowEnabled = false;
|
|
|
|
|
bool telemetryEnabled = true;
|
2019-09-14 15:22:54 -05:00
|
|
|
|
|
|
|
|
std::shared_ptr<Component> GetOrAdd(Sendable* sendable);
|
2017-12-04 23:28:33 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
LiveWindow::Impl::Impl()
|
2019-09-14 15:22:54 -05:00
|
|
|
: registry(SendableRegistry::GetInstance()),
|
|
|
|
|
dataHandle(registry.GetDataHandle()),
|
|
|
|
|
liveWindowTable(
|
2017-12-04 23:28:33 -08:00
|
|
|
nt::NetworkTableInstance::GetDefault().GetTable("LiveWindow")) {
|
|
|
|
|
statusTable = liveWindowTable->GetSubTable(".status");
|
|
|
|
|
enabledEntry = statusTable->GetEntry("LW Enabled");
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-14 15:22:54 -05:00
|
|
|
std::shared_ptr<LiveWindow::Impl::Component> LiveWindow::Impl::GetOrAdd(
|
|
|
|
|
Sendable* sendable) {
|
|
|
|
|
auto data = std::static_pointer_cast<Component>(
|
|
|
|
|
registry.GetData(sendable, dataHandle));
|
|
|
|
|
if (!data) {
|
|
|
|
|
data = std::make_shared<Component>();
|
|
|
|
|
registry.SetData(sendable, dataHandle, data);
|
|
|
|
|
}
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-21 11:13:49 -07:00
|
|
|
LiveWindow& LiveWindow::GetInstance() {
|
2015-06-24 04:25:10 -07:00
|
|
|
static LiveWindow instance;
|
2021-03-21 11:13:49 -07:00
|
|
|
return instance;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2017-12-04 23:28:33 -08:00
|
|
|
void LiveWindow::EnableTelemetry(Sendable* sendable) {
|
2019-07-08 22:58:39 -07:00
|
|
|
std::scoped_lock lock(m_impl->mutex);
|
2017-12-04 23:28:33 -08:00
|
|
|
// Re-enable global setting in case DisableAllTelemetry() was called.
|
|
|
|
|
m_impl->telemetryEnabled = true;
|
2019-09-14 15:22:54 -05:00
|
|
|
m_impl->GetOrAdd(sendable)->telemetryEnabled = true;
|
2017-12-04 23:28:33 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LiveWindow::DisableTelemetry(Sendable* sendable) {
|
2019-07-08 22:58:39 -07:00
|
|
|
std::scoped_lock lock(m_impl->mutex);
|
2019-09-14 15:22:54 -05:00
|
|
|
m_impl->GetOrAdd(sendable)->telemetryEnabled = false;
|
2017-12-04 23:28:33 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LiveWindow::DisableAllTelemetry() {
|
2019-07-08 22:58:39 -07:00
|
|
|
std::scoped_lock lock(m_impl->mutex);
|
2017-12-04 23:28:33 -08:00
|
|
|
m_impl->telemetryEnabled = false;
|
2019-10-17 22:01:31 -07:00
|
|
|
m_impl->registry.ForeachLiveWindow(m_impl->dataHandle, [&](auto& cbdata) {
|
2020-12-28 12:58:06 -08:00
|
|
|
if (!cbdata.data) {
|
|
|
|
|
cbdata.data = std::make_shared<Impl::Component>();
|
|
|
|
|
}
|
2019-10-17 22:01:31 -07:00
|
|
|
std::static_pointer_cast<Impl::Component>(cbdata.data)->telemetryEnabled =
|
|
|
|
|
false;
|
|
|
|
|
});
|
2017-12-04 23:28:33 -08:00
|
|
|
}
|
|
|
|
|
|
2018-05-31 20:47:15 -07:00
|
|
|
bool LiveWindow::IsEnabled() const {
|
2019-07-08 22:58:39 -07:00
|
|
|
std::scoped_lock lock(m_impl->mutex);
|
2018-05-31 20:47:15 -07:00
|
|
|
return m_impl->liveWindowEnabled;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LiveWindow::SetEnabled(bool enabled) {
|
2019-07-08 22:58:39 -07:00
|
|
|
std::scoped_lock lock(m_impl->mutex);
|
2020-12-28 12:58:06 -08:00
|
|
|
if (m_impl->liveWindowEnabled == enabled) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-12-07 22:38:22 -05:00
|
|
|
m_impl->startLiveWindow = enabled;
|
|
|
|
|
m_impl->liveWindowEnabled = enabled;
|
|
|
|
|
// Force table generation now to make sure everything is defined
|
|
|
|
|
UpdateValuesUnsafe();
|
2018-05-31 20:47:15 -07:00
|
|
|
if (enabled) {
|
2020-12-28 12:58:06 -08:00
|
|
|
if (this->enabled) {
|
|
|
|
|
this->enabled();
|
|
|
|
|
}
|
2018-05-31 20:47:15 -07:00
|
|
|
} else {
|
2019-10-17 22:01:31 -07:00
|
|
|
m_impl->registry.ForeachLiveWindow(m_impl->dataHandle, [&](auto& cbdata) {
|
|
|
|
|
cbdata.builder.StopLiveWindowMode();
|
|
|
|
|
});
|
2020-12-28 12:58:06 -08:00
|
|
|
if (this->disabled) {
|
|
|
|
|
this->disabled();
|
|
|
|
|
}
|
2018-05-31 20:47:15 -07:00
|
|
|
}
|
|
|
|
|
m_impl->enabledEntry.SetBoolean(enabled);
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-04 23:28:33 -08:00
|
|
|
void LiveWindow::UpdateValues() {
|
2019-07-08 22:58:39 -07:00
|
|
|
std::scoped_lock lock(m_impl->mutex);
|
2018-12-07 22:38:22 -05:00
|
|
|
UpdateValuesUnsafe();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LiveWindow::UpdateValuesUnsafe() {
|
2017-12-04 23:28:33 -08:00
|
|
|
// Only do this if either LiveWindow mode or telemetry is enabled.
|
2020-12-28 12:58:06 -08:00
|
|
|
if (!m_impl->liveWindowEnabled && !m_impl->telemetryEnabled) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2017-12-04 23:28:33 -08:00
|
|
|
|
2019-10-17 22:01:31 -07:00
|
|
|
m_impl->registry.ForeachLiveWindow(m_impl->dataHandle, [&](auto& cbdata) {
|
2020-12-28 12:58:06 -08:00
|
|
|
if (!cbdata.sendable || cbdata.parent) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-10-17 22:01:31 -07:00
|
|
|
|
2020-12-28 12:58:06 -08:00
|
|
|
if (!cbdata.data) {
|
|
|
|
|
cbdata.data = std::make_shared<Impl::Component>();
|
|
|
|
|
}
|
2019-10-17 22:01:31 -07:00
|
|
|
|
|
|
|
|
auto& comp = *std::static_pointer_cast<Impl::Component>(cbdata.data);
|
|
|
|
|
|
2020-12-28 12:58:06 -08:00
|
|
|
if (!m_impl->liveWindowEnabled && !comp.telemetryEnabled) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-10-17 22:01:31 -07:00
|
|
|
|
|
|
|
|
if (comp.firstTime) {
|
|
|
|
|
// By holding off creating the NetworkTable entries, it allows the
|
|
|
|
|
// components to be redefined. This allows default sensor and actuator
|
|
|
|
|
// values to be created that are replaced with the custom names from
|
|
|
|
|
// users calling setName.
|
2020-12-28 12:58:06 -08:00
|
|
|
if (cbdata.name.empty()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-10-17 22:01:31 -07:00
|
|
|
auto ssTable = m_impl->liveWindowTable->GetSubTable(cbdata.subsystem);
|
2021-04-04 14:34:11 -07:00
|
|
|
std::shared_ptr<nt::NetworkTable> table;
|
2019-10-17 22:01:31 -07:00
|
|
|
// Treat name==subsystem as top level of subsystem
|
2020-12-28 12:58:06 -08:00
|
|
|
if (cbdata.name == cbdata.subsystem) {
|
2019-10-17 22:01:31 -07:00
|
|
|
table = ssTable;
|
2020-12-28 12:58:06 -08:00
|
|
|
} else {
|
2019-10-17 22:01:31 -07:00
|
|
|
table = ssTable->GetSubTable(cbdata.name);
|
2020-12-28 12:58:06 -08:00
|
|
|
}
|
2019-10-17 22:01:31 -07:00
|
|
|
table->GetEntry(".name").SetString(cbdata.name);
|
|
|
|
|
cbdata.builder.SetTable(table);
|
|
|
|
|
cbdata.sendable->InitSendable(cbdata.builder);
|
|
|
|
|
ssTable->GetEntry(".type").SetString("LW Subsystem");
|
|
|
|
|
|
|
|
|
|
comp.firstTime = false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-28 12:58:06 -08:00
|
|
|
if (m_impl->startLiveWindow) {
|
|
|
|
|
cbdata.builder.StartLiveWindowMode();
|
|
|
|
|
}
|
2019-10-17 22:01:31 -07:00
|
|
|
cbdata.builder.UpdateTable();
|
|
|
|
|
});
|
2017-12-04 23:28:33 -08:00
|
|
|
|
|
|
|
|
m_impl->startLiveWindow = false;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
2018-05-31 20:47:15 -07:00
|
|
|
|
|
|
|
|
LiveWindow::LiveWindow() : m_impl(new Impl) {}
|