// 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. #include "frc/smartdashboard/SendableBuilderImpl.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "frc/smartdashboard/SmartDashboard.h" using namespace frc; template void SendableBuilderImpl::PropertyImpl::Update(bool controllable, int64_t time) { if (controllable && sub && updateLocal) { updateLocal(sub); } if (pub && updateNetwork) { updateNetwork(pub, time); } } void SendableBuilderImpl::SetTable(std::shared_ptr table) { m_table = table; m_controllablePublisher = table->GetBooleanTopic(".controllable").Publish(); m_controllablePublisher.SetDefault(false); } std::shared_ptr SendableBuilderImpl::GetTable() { return m_table; } bool SendableBuilderImpl::IsPublished() const { return m_table != nullptr; } bool SendableBuilderImpl::IsActuator() const { return m_actuator; } void SendableBuilderImpl::Update() { uint64_t time = nt::Now(); for (auto& property : m_properties) { property->Update(m_controllable, time); } for (auto& updateTable : m_updateTables) { updateTable(); } } void SendableBuilderImpl::StartListeners() { m_controllable = true; if (m_controllablePublisher) { m_controllablePublisher.Set(true); } } void SendableBuilderImpl::StopListeners() { m_controllable = false; if (m_controllablePublisher) { m_controllablePublisher.Set(false); } } void SendableBuilderImpl::StartLiveWindowMode() { if (m_safeState) { m_safeState(); } StartListeners(); } void SendableBuilderImpl::StopLiveWindowMode() { StopListeners(); if (m_safeState) { m_safeState(); } } void SendableBuilderImpl::ClearProperties() { m_properties.clear(); } void SendableBuilderImpl::SetSmartDashboardType(std::string_view type) { if (!m_typePublisher) { m_typePublisher = m_table->GetStringTopic(".type").Publish(); } m_typePublisher.Set(type); } void SendableBuilderImpl::SetActuator(bool value) { if (!m_actuatorPublisher) { m_actuatorPublisher = m_table->GetBooleanTopic(".actuator").Publish(); } m_actuatorPublisher.Set(value); m_actuator = value; } void SendableBuilderImpl::SetSafeState(std::function func) { m_safeState = func; } void SendableBuilderImpl::SetUpdateTable(wpi::unique_function func) { m_updateTables.emplace_back(std::move(func)); } nt::Topic SendableBuilderImpl::GetTopic(std::string_view key) { return m_table->GetTopic(key); } template void SendableBuilderImpl::AddPropertyImpl(Topic topic, Getter getter, Setter setter) { auto prop = std::make_unique>(); if (getter) { prop->pub = topic.Publish(); prop->updateNetwork = [=](auto& pub, int64_t time) { pub.Set(getter(), time); }; } if (setter) { prop->sub = topic.Subscribe( {}, {{nt::PubSubOption::ExcludePublisher(prop->pub.GetHandle())}}); prop->updateLocal = [=](auto& sub) { for (auto&& val : sub.ReadQueue()) { setter(val.value); } }; } m_properties.emplace_back(std::move(prop)); } void SendableBuilderImpl::AddBooleanProperty(std::string_view key, std::function getter, std::function setter) { AddPropertyImpl(m_table->GetBooleanTopic(key), std::move(getter), std::move(setter)); } void SendableBuilderImpl::AddIntegerProperty( std::string_view key, std::function getter, std::function setter) { AddPropertyImpl(m_table->GetIntegerTopic(key), std::move(getter), std::move(setter)); } void SendableBuilderImpl::AddFloatProperty(std::string_view key, std::function getter, std::function setter) { AddPropertyImpl(m_table->GetFloatTopic(key), std::move(getter), std::move(setter)); } void SendableBuilderImpl::AddDoubleProperty( std::string_view key, std::function getter, std::function setter) { AddPropertyImpl(m_table->GetDoubleTopic(key), std::move(getter), std::move(setter)); } void SendableBuilderImpl::AddStringProperty( std::string_view key, std::function getter, std::function setter) { AddPropertyImpl(m_table->GetStringTopic(key), std::move(getter), std::move(setter)); } void SendableBuilderImpl::AddBooleanArrayProperty( std::string_view key, std::function()> getter, std::function)> setter) { AddPropertyImpl(m_table->GetBooleanArrayTopic(key), std::move(getter), std::move(setter)); } void SendableBuilderImpl::AddIntegerArrayProperty( std::string_view key, std::function()> getter, std::function)> setter) { AddPropertyImpl(m_table->GetIntegerArrayTopic(key), std::move(getter), std::move(setter)); } void SendableBuilderImpl::AddFloatArrayProperty( std::string_view key, std::function()> getter, std::function)> setter) { AddPropertyImpl(m_table->GetFloatArrayTopic(key), std::move(getter), std::move(setter)); } void SendableBuilderImpl::AddDoubleArrayProperty( std::string_view key, std::function()> getter, std::function)> setter) { AddPropertyImpl(m_table->GetDoubleArrayTopic(key), std::move(getter), std::move(setter)); } void SendableBuilderImpl::AddStringArrayProperty( std::string_view key, std::function()> getter, std::function)> setter) { AddPropertyImpl(m_table->GetStringArrayTopic(key), std::move(getter), std::move(setter)); } void SendableBuilderImpl::AddRawProperty( std::string_view key, std::string_view typeString, std::function()> getter, std::function)> setter) { auto topic = m_table->GetRawTopic(key); auto prop = std::make_unique>(); if (getter) { prop->pub = topic.Publish(typeString); prop->updateNetwork = [=](auto& pub, int64_t time) { pub.Set(getter(), time); }; } if (setter) { prop->sub = topic.Subscribe( typeString, {}, {{nt::PubSubOption::ExcludePublisher(prop->pub.GetHandle())}}); prop->updateLocal = [=](auto& sub) { for (auto&& val : sub.ReadQueue()) { setter(val.value); } }; } m_properties.emplace_back(std::move(prop)); } template void SendableBuilderImpl::AddSmallPropertyImpl(Topic topic, Getter getter, Setter setter) { auto prop = std::make_unique>(); if (getter) { prop->pub = topic.Publish(); prop->updateNetwork = [=](auto& pub, int64_t time) { wpi::SmallVector buf; pub.Set(getter(buf), time); }; } if (setter) { prop->sub = topic.Subscribe( {}, {{nt::PubSubOption::ExcludePublisher(prop->pub.GetHandle())}}); prop->updateLocal = [=](auto& sub) { for (auto&& val : sub.ReadQueue()) { setter(val.value); } }; } m_properties.emplace_back(std::move(prop)); } void SendableBuilderImpl::AddSmallStringProperty( std::string_view key, std::function& buf)> getter, std::function setter) { AddSmallPropertyImpl(m_table->GetStringTopic(key), std::move(getter), std::move(setter)); } void SendableBuilderImpl::AddSmallBooleanArrayProperty( std::string_view key, std::function(wpi::SmallVectorImpl& buf)> getter, std::function)> setter) { AddSmallPropertyImpl(m_table->GetBooleanArrayTopic(key), std::move(getter), std::move(setter)); } void SendableBuilderImpl::AddSmallIntegerArrayProperty( std::string_view key, std::function(wpi::SmallVectorImpl& buf)> getter, std::function)> setter) { AddSmallPropertyImpl(m_table->GetIntegerArrayTopic(key), std::move(getter), std::move(setter)); } void SendableBuilderImpl::AddSmallFloatArrayProperty( std::string_view key, std::function(wpi::SmallVectorImpl& buf)> getter, std::function)> setter) { AddSmallPropertyImpl(m_table->GetFloatArrayTopic(key), std::move(getter), std::move(setter)); } void SendableBuilderImpl::AddSmallDoubleArrayProperty( std::string_view key, std::function(wpi::SmallVectorImpl& buf)> getter, std::function)> setter) { AddSmallPropertyImpl(m_table->GetDoubleArrayTopic(key), std::move(getter), std::move(setter)); } void SendableBuilderImpl::AddSmallStringArrayProperty( std::string_view key, std::function< std::span(wpi::SmallVectorImpl& buf)> getter, std::function)> setter) { AddSmallPropertyImpl(m_table->GetStringArrayTopic(key), std::move(getter), std::move(setter)); } void SendableBuilderImpl::AddSmallRawProperty( std::string_view key, std::string_view typeString, std::function(wpi::SmallVectorImpl& buf)> getter, std::function)> setter) { auto topic = m_table->GetRawTopic(key); auto prop = std::make_unique>(); if (getter) { prop->pub = topic.Publish(typeString); prop->updateNetwork = [=](auto& pub, int64_t time) { wpi::SmallVector buf; pub.Set(getter(buf), time); }; } if (setter) { prop->sub = topic.Subscribe( typeString, {}, {{nt::PubSubOption::ExcludePublisher(prop->pub.GetHandle())}}); prop->updateLocal = [=](auto& sub) { for (auto&& val : sub.ReadQueue()) { setter(val.value); } }; } m_properties.emplace_back(std::move(prop)); }