Split Sendable into NT and non-NT portions (#3432)

The non-NT portion has been moved to wpiutil.
The NT portion has been moved to ntcore (as NTSendable).

SendableBuilder similarly split and moved.

SendableRegistry moved to wpiutil.

In C++, SendableHelper also moved to wpiutil.

This enables use of Sendable from wpimath and also enables
moving several classes from wpilib to wpimath.
This commit is contained in:
Peter Johnson
2021-06-13 16:38:05 -07:00
committed by GitHub
parent ef4ea84cb5
commit b417d961ec
196 changed files with 1147 additions and 891 deletions

View File

@@ -0,0 +1,26 @@
// 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.
#pragma once
namespace wpi {
class SendableBuilder;
/**
* Interface for Sendable objects.
*/
class Sendable {
public:
virtual ~Sendable() = default;
/**
* Initializes this Sendable object.
*
* @param builder sendable builder
*/
virtual void InitSendable(SendableBuilder& builder) = 0;
};
} // namespace wpi

View File

@@ -0,0 +1,217 @@
// 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.
#pragma once
#include <functional>
#include <memory>
#include <string>
#include <string_view>
#include <vector>
#include "wpi/SmallVector.h"
#include "wpi/span.h"
namespace wpi {
class SendableBuilder {
public:
/**
* The backend kinds used for the sendable builder.
*/
enum BackendKind { kUnknown, kNetworkTables };
virtual ~SendableBuilder() = default;
/**
* Set the string representation of the named data type that will be used
* by the smart dashboard for this sendable.
*
* @param type data type
*/
virtual void SetSmartDashboardType(std::string_view type) = 0;
/**
* Set a flag indicating if this sendable should be treated as an actuator.
* By default this flag is false.
*
* @param value true if actuator, false if not
*/
virtual void SetActuator(bool value) = 0;
/**
* Set the function that should be called to set the Sendable into a safe
* state. This is called when entering and exiting Live Window mode.
*
* @param func function
*/
virtual void SetSafeState(std::function<void()> func) = 0;
/**
* Add a boolean property.
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddBooleanProperty(std::string_view key,
std::function<bool()> getter,
std::function<void(bool)> setter) = 0;
/**
* Add a double property.
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddDoubleProperty(std::string_view key,
std::function<double()> getter,
std::function<void(double)> setter) = 0;
/**
* Add a string property.
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddStringProperty(
std::string_view key, std::function<std::string()> getter,
std::function<void(std::string_view)> setter) = 0;
/**
* Add a boolean array property.
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddBooleanArrayProperty(
std::string_view key, std::function<std::vector<int>()> getter,
std::function<void(wpi::span<const int>)> setter) = 0;
/**
* Add a double array property.
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddDoubleArrayProperty(
std::string_view key, std::function<std::vector<double>()> getter,
std::function<void(wpi::span<const double>)> setter) = 0;
/**
* Add a string array property.
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddStringArrayProperty(
std::string_view key, std::function<std::vector<std::string>()> getter,
std::function<void(wpi::span<const std::string>)> setter) = 0;
/**
* Add a raw property.
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddRawProperty(std::string_view key,
std::function<std::string()> getter,
std::function<void(std::string_view)> setter) = 0;
/**
* Add a string property (SmallString form).
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddSmallStringProperty(
std::string_view key,
std::function<std::string_view(wpi::SmallVectorImpl<char>& buf)> getter,
std::function<void(std::string_view)> setter) = 0;
/**
* Add a boolean array property (SmallVector form).
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddSmallBooleanArrayProperty(
std::string_view key,
std::function<wpi::span<const int>(wpi::SmallVectorImpl<int>& buf)>
getter,
std::function<void(wpi::span<const int>)> setter) = 0;
/**
* Add a double array property (SmallVector form).
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddSmallDoubleArrayProperty(
std::string_view key,
std::function<wpi::span<const double>(wpi::SmallVectorImpl<double>& buf)>
getter,
std::function<void(wpi::span<const double>)> setter) = 0;
/**
* Add a string array property (SmallVector form).
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddSmallStringArrayProperty(
std::string_view key,
std::function<
wpi::span<const std::string>(wpi::SmallVectorImpl<std::string>& buf)>
getter,
std::function<void(wpi::span<const std::string>)> setter) = 0;
/**
* Add a raw property (SmallVector form).
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddSmallRawProperty(
std::string_view key,
std::function<std::string_view(wpi::SmallVectorImpl<char>& buf)> getter,
std::function<void(std::string_view)> setter) = 0;
/**
* Gets the kind of backend being used.
*
* @return Backend kind
*/
virtual BackendKind GetBackendKind() const = 0;
/**
* Return whether this sendable has been published.
*
* @return True if it has been published, false if not.
*/
virtual bool IsPublished() const = 0;
/**
* Update the published values by calling the getters for all properties.
*/
virtual void Update() = 0;
/**
* Clear properties.
*/
virtual void ClearProperties() = 0;
};
} // namespace wpi

View File

@@ -0,0 +1,175 @@
// 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.
#pragma once
#include <memory>
#include <string>
#include <string_view>
#include "wpi/deprecated.h"
#include "wpi/sendable/SendableRegistry.h"
namespace wpi {
/**
* A helper class for use with objects that add themselves to SendableRegistry.
* It takes care of properly calling Move() and Remove() on move and
* destruction. No action is taken if the object is copied.
* Use public inheritance with CRTP when using this class.
* @tparam CRTP derived class
*/
template <typename Derived>
class SendableHelper {
public:
SendableHelper(const SendableHelper& rhs) = default;
SendableHelper& operator=(const SendableHelper& rhs) = default;
SendableHelper(SendableHelper&& rhs) {
// it is safe to call Move() multiple times with the same rhs
SendableRegistry::GetInstance().Move(static_cast<Derived*>(this),
static_cast<Derived*>(&rhs));
}
SendableHelper& operator=(SendableHelper&& rhs) {
// it is safe to call Move() multiple times with the same rhs
SendableRegistry::GetInstance().Move(static_cast<Derived*>(this),
static_cast<Derived*>(&rhs));
return *this;
}
/**
* Gets the name of this Sendable object.
*
* @deprecated use SendableRegistry::GetName()
*
* @return Name
*/
WPI_DEPRECATED("use SendableRegistry::GetName()")
std::string GetName() const {
return SendableRegistry::GetInstance().GetName(
static_cast<const Derived*>(this));
}
/**
* Sets the name of this Sendable object.
*
* @deprecated use SendableRegistry::SetName()
*
* @param name name
*/
WPI_DEPRECATED("use SendableRegistry::SetName()")
void SetName(std::string_view name) {
SendableRegistry::GetInstance().SetName(static_cast<Derived*>(this), name);
}
/**
* Sets both the subsystem name and device name of this Sendable object.
*
* @deprecated use SendableRegistry::SetName()
*
* @param subsystem subsystem name
* @param name device name
*/
WPI_DEPRECATED("use SendableRegistry::SetName()")
void SetName(std::string_view subsystem, std::string_view name) {
SendableRegistry::GetInstance().SetName(static_cast<Derived*>(this),
subsystem, name);
}
/**
* Gets the subsystem name of this Sendable object.
*
* @deprecated use SendableRegistry::GetSubsystem().
*
* @return Subsystem name
*/
WPI_DEPRECATED("use SendableRegistry::GetSubsystem()")
std::string GetSubsystem() const {
return SendableRegistry::GetInstance().GetSubsystem(
static_cast<const Derived*>(this));
}
/**
* Sets the subsystem name of this Sendable object.
*
* @deprecated use SendableRegistry::SetSubsystem()
*
* @param subsystem subsystem name
*/
WPI_DEPRECATED("use SendableRegistry::SetSubsystem()")
void SetSubsystem(std::string_view subsystem) {
SendableRegistry::GetInstance().SetSubsystem(static_cast<Derived*>(this),
subsystem);
}
protected:
/**
* Add a child component.
*
* @deprecated use SendableRegistry::AddChild()
*
* @param child child component
*/
WPI_DEPRECATED("use SendableRegistry::AddChild()")
void AddChild(std::shared_ptr<Sendable> child) {
SendableRegistry::GetInstance().AddChild(static_cast<Derived*>(this),
child.get());
}
/**
* Add a child component.
*
* @deprecated use SendableRegistry::AddChild()
*
* @param child child component
*/
WPI_DEPRECATED("use SendableRegistry::AddChild()")
void AddChild(void* child) {
SendableRegistry::GetInstance().AddChild(static_cast<Derived*>(this),
child);
}
/**
* Sets the name of the sensor with a channel number.
*
* @deprecated use SendableRegistry::SetName()
*
* @param moduleType A string that defines the module name in the label for
* the value
* @param channel The channel number the device is plugged into
*/
WPI_DEPRECATED("use SendableRegistry::SetName()")
void SetName(std::string_view moduleType, int channel) {
SendableRegistry::GetInstance().SetName(static_cast<Derived*>(this),
moduleType, channel);
}
/**
* Sets the name of the sensor with a module and channel number.
*
* @deprecated use SendableRegistry::SetName()
*
* @param moduleType A string that defines the module name in the label for
* the value
* @param moduleNumber The number of the particular module type
* @param channel The channel number the device is plugged into (usually
* PWM)
*/
WPI_DEPRECATED("use SendableRegistry::SetName()")
void SetName(std::string_view moduleType, int moduleNumber, int channel) {
SendableRegistry::GetInstance().SetName(static_cast<Derived*>(this),
moduleType, moduleNumber, channel);
}
protected:
SendableHelper() = default;
~SendableHelper() {
// it is safe to call Remove() multiple times with the same object
SendableRegistry::GetInstance().Remove(static_cast<Derived*>(this));
}
};
} // namespace wpi

View File

@@ -0,0 +1,346 @@
// 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.
#pragma once
#include <functional>
#include <memory>
#include <string>
#include <string_view>
#include "wpi/function_ref.h"
namespace wpi {
class Sendable;
class SendableBuilder;
/**
* The SendableRegistry class is the public interface for registering sensors
* and actuators for use on dashboards and LiveWindow.
*/
class SendableRegistry {
public:
SendableRegistry(const SendableRegistry&) = delete;
SendableRegistry& operator=(const SendableRegistry&) = delete;
using UID = size_t;
/**
* Gets an instance of the SendableRegistry class.
*
* This is a singleton to guarantee that there is only a single instance
* regardless of how many times GetInstance is called.
*/
static SendableRegistry& GetInstance();
/**
* Sets the factory for LiveWindow builders.
*
* @param factory factory function
*/
void SetLiveWindowBuilderFactory(
std::function<std::unique_ptr<SendableBuilder>()> factory);
/**
* Adds an object to the registry.
*
* @param sendable object to add
* @param name component name
*/
void Add(Sendable* sendable, std::string_view name);
/**
* Adds an object to the registry.
*
* @param sendable object to add
* @param moduleType A string that defines the module name in the label for
* the value
* @param channel The channel number the device is plugged into
*/
void Add(Sendable* sendable, std::string_view moduleType, int channel);
/**
* Adds an object to the registry.
*
* @param sendable object to add
* @param moduleType A string that defines the module name in the label for
* the value
* @param moduleNumber The number of the particular module type
* @param channel The channel number the device is plugged into
*/
void Add(Sendable* sendable, std::string_view moduleType, int moduleNumber,
int channel);
/**
* Adds an object to the registry.
*
* @param sendable object to add
* @param subsystem subsystem name
* @param name component name
*/
void Add(Sendable* sendable, std::string_view subsystem,
std::string_view name);
/**
* Adds an object to the registry and LiveWindow.
*
* @param sendable object to add
* @param name component name
*/
void AddLW(Sendable* sendable, std::string_view name);
/**
* Adds an object to the registry and LiveWindow.
*
* @param sendable object to add
* @param moduleType A string that defines the module name in the label for
* the value
* @param channel The channel number the device is plugged into
*/
void AddLW(Sendable* sendable, std::string_view moduleType, int channel);
/**
* Adds an object to the registry and LiveWindow.
*
* @param sendable object to add
* @param moduleType A string that defines the module name in the label for
* the value
* @param moduleNumber The number of the particular module type
* @param channel The channel number the device is plugged into
*/
void AddLW(Sendable* sendable, std::string_view moduleType, int moduleNumber,
int channel);
/**
* Adds an object to the registry and LiveWindow.
*
* @param sendable object to add
* @param subsystem subsystem name
* @param name component name
*/
void AddLW(Sendable* sendable, std::string_view subsystem,
std::string_view name);
/**
* Adds a child object to an object. Adds the child object to the registry
* if it's not already present.
*
* @param parent parent object
* @param child child object
*/
void AddChild(Sendable* parent, Sendable* child);
/**
* Adds a child object to an object. Adds the child object to the registry
* if it's not already present.
*
* @param parent parent object
* @param child child object
*/
void AddChild(Sendable* parent, void* child);
/**
* Removes an object from the registry.
*
* @param sendable object to remove
* @return true if the object was removed; false if it was not present
*/
bool Remove(Sendable* sendable);
/**
* Moves an object in the registry (for use in move constructors/assignments).
*
* @param to new object
* @param from old object
*/
void Move(Sendable* to, Sendable* from);
/**
* Determines if an object is in the registry.
*
* @param sendable object to check
* @return True if in registry, false if not.
*/
bool Contains(const Sendable* sendable) const;
/**
* Gets the name of an object.
*
* @param sendable object
* @return Name (empty if object is not in registry)
*/
std::string GetName(const Sendable* sendable) const;
/**
* Sets the name of an object.
*
* @param sendable object
* @param name name
*/
void SetName(Sendable* sendable, std::string_view name);
/**
* Sets the name of an object with a channel number.
*
* @param sendable object
* @param moduleType A string that defines the module name in the label for
* the value
* @param channel The channel number the device is plugged into
*/
void SetName(Sendable* sendable, std::string_view moduleType, int channel);
/**
* Sets the name of an object with a module and channel number.
*
* @param sendable object
* @param moduleType A string that defines the module name in the label for
* the value
* @param moduleNumber The number of the particular module type
* @param channel The channel number the device is plugged into
*/
void SetName(Sendable* sendable, std::string_view moduleType,
int moduleNumber, int channel);
/**
* Sets both the subsystem name and device name of an object.
*
* @param sendable object
* @param subsystem subsystem name
* @param name device name
*/
void SetName(Sendable* sendable, std::string_view subsystem,
std::string_view name);
/**
* Gets the subsystem name of an object.
*
* @param sendable object
* @return Subsystem name (empty if object is not in registry)
*/
std::string GetSubsystem(const Sendable* sendable) const;
/**
* Sets the subsystem name of an object.
*
* @param sendable object
* @param subsystem subsystem name
*/
void SetSubsystem(Sendable* sendable, std::string_view subsystem);
/**
* Gets a unique handle for setting/getting data with SetData() and GetData().
*
* @return Handle
*/
int GetDataHandle();
/**
* Associates arbitrary data with an object in the registry.
*
* @param sendable object
* @param handle data handle returned by GetDataHandle()
* @param data data to set
* @return Previous data (may be null)
*/
std::shared_ptr<void> SetData(Sendable* sendable, int handle,
std::shared_ptr<void> data);
/**
* Gets arbitrary data associated with an object in the registry.
*
* @param sendable object
* @param handle data handle returned by GetDataHandle()
* @return data (may be null if none associated)
*/
std::shared_ptr<void> GetData(Sendable* sendable, int handle);
/**
* Enables LiveWindow for an object.
*
* @param sendable object
*/
void EnableLiveWindow(Sendable* sendable);
/**
* Disables LiveWindow for an object.
*
* @param sendable object
*/
void DisableLiveWindow(Sendable* sendable);
/**
* Get unique id for an object. Since objects can move, use this instead
* of storing Sendable* directly if ownership is in question.
*
* @param sendable object
* @return unique id
*/
UID GetUniqueId(Sendable* sendable);
/**
* Get sendable object for a given unique id.
*
* @param uid unique id
* @return sendable object (may be null)
*/
Sendable* GetSendable(UID uid);
/**
* Publishes an object in the registry.
*
* @param sendableUid sendable unique id
* @param builder publisher backend
*/
void Publish(UID sendableUid, std::unique_ptr<SendableBuilder> builder);
/**
* Updates published information from an object.
*
* @param sendableUid sendable unique id
*/
void Update(UID sendableUid);
/**
* Data passed to ForeachLiveWindow() callback function
*/
struct CallbackData {
CallbackData(Sendable* sendable_, std::string_view name_,
std::string_view subsystem_, wpi::Sendable* parent_,
std::shared_ptr<void>& data_, SendableBuilder& builder_)
: sendable(sendable_),
name(name_),
subsystem(subsystem_),
parent(parent_),
data(data_),
builder(builder_) {}
Sendable* sendable;
std::string_view name;
std::string_view subsystem;
Sendable* parent;
std::shared_ptr<void>& data;
SendableBuilder& builder;
};
/**
* Iterates over LiveWindow-enabled objects in the registry.
* It is *not* safe to call other SendableRegistry functions from the
* callback (this will likely deadlock).
*
* @param dataHandle data handle to get data pointer passed to callback
* @param callback function to call for each object
*/
void ForeachLiveWindow(
int dataHandle,
wpi::function_ref<void(CallbackData& cbdata)> callback) const;
private:
SendableRegistry();
struct Impl;
std::unique_ptr<Impl> m_impl;
};
} // namespace wpi