18#include <initializer_list>
23#include <units/base.h>
24#include <units/frequency.h>
25#include <units/time.h>
63 this->units = other.
units;
66 this->error = other.
error;
73 std::function<
void()> checkFirmVersFunction) :
105 double timeoutSeconds);
107 static ctre::phoenix::StatusCode
Status_SetUpdateFrequency(
const char *canbus, uint32_t deviceHash, uint16_t spn,
double frequencyHz,
double timeoutSeconds);
137 bool bWaitForUpdate,
double timeoutSeconds,
139 double *hwtimestamp,
double *swtimestamp,
double *ecutimestamp);
150 template <
typename Arr>
151 static ctre::phoenix::StatusCode
WaitForAllImpl(
const char *location, units::time::second_t timeoutSeconds,
const Arr &signals)
153 if (signals.size() < 1)
158 retval.GetDescription(),
163 const std::string &network = signals[0]->deviceIdentifier.network;
165 for (
auto signal : signals)
168 if (network != signal->deviceIdentifier.network)
173 retval.GetDescription(),
181 for (
auto signal : signals)
183 signal->_checkFirmVersFunction();
187 ctre::phoenix::StatusCode retval = Status_WaitForAll(signals.data(), signals.size(), network.c_str(), timeoutSeconds.to<
double>());
190 if (
false == retval.IsOK())
193 retval.GetDescription(),
203 template <
typename... Signals>
205 std::conjunction<std::is_base_of<BaseStatusSignal, std::remove_reference_t<Signals>>...>
211 template <
typename... Signals>
240 template <
typename... Signals,
typename = std::enable_if_t<is_all_status_signal_v<Signals...>>>
241 static ctre::phoenix::StatusCode
WaitForAll(units::time::second_t timeoutSeconds, Signals &... signals)
243 return WaitForAll(timeoutSeconds,
269 static ctre::phoenix::StatusCode
WaitForAll(units::time::second_t timeoutSeconds,
const std::vector<BaseStatusSignal *> &signals)
272 constexpr char kLocation[] =
"ctre::phoenix6::BaseStatusSignal::WaitForAll";
273 return WaitForAllImpl(kLocation, timeoutSeconds, signals);
299 static ctre::phoenix::StatusCode
WaitForAll(units::time::second_t timeoutSeconds,
const std::array<BaseStatusSignal *, N> &signals)
302 constexpr char kLocation[] =
"ctre::phoenix6::BaseStatusSignal::WaitForAll";
303 return WaitForAllImpl(kLocation, timeoutSeconds, signals);
319 template <
typename... Signals,
typename = std::enable_if_t<is_all_status_signal_v<Signals...>>>
320 static ctre::phoenix::StatusCode
RefreshAll(Signals &... signals)
322 return RefreshAll(std::array<
BaseStatusSignal *,
sizeof...(Signals)>{(&signals)...});
337 static ctre::phoenix::StatusCode
RefreshAll(
const std::vector<BaseStatusSignal *> &signals)
340 constexpr char kLocation[] =
"ctre::phoenix6::BaseStatusSignal::RefreshAll";
341 return WaitForAllImpl(kLocation, 0_s, signals);
357 static ctre::phoenix::StatusCode
RefreshAll(
const std::array<BaseStatusSignal *, N> &signals)
360 constexpr char kLocation[] =
"ctre::phoenix6::BaseStatusSignal::RefreshAll";
361 return WaitForAllImpl(kLocation, 0_s, signals);
386 template <
typename U,
typename U_PER_SEC>
389 static_assert(units::traits::is_unit_t_v<U>,
"signal must be a unit signal");
390 static_assert(units::traits::is_unit_t_v<U_PER_SEC>,
"signalSlope must be a unit signal");
391 using lhs =
typename units::traits::unit_t_traits<U>::unit_type;
392 using rhs =
typename units::traits::unit_t_traits<U_PER_SEC>::unit_type;
393 static_assert(units::traits::is_convertible_unit_v<lhs, units::compound_unit<rhs, units::seconds>>,
394 "Compensation can only be performed on a signal with its derivative");
396 const U nonCompensatedSignal = signal.
GetValue();
397 const U_PER_SEC changeInSignal = signalSlope.
GetValue();
399 if (maxLatencySeconds > 0_s && latency > maxLatencySeconds) {
400 latency = maxLatencySeconds;
402 return nonCompensatedSignal + (changeInSignal * latency);
411 template <
typename... Signals,
typename = std::enable_if_t<is_all_status_signal_v<Signals...>>>
414 return IsAllGood(std::array<
BaseStatusSignal *,
sizeof...(Signals)>{(&signals)...});
422 static bool IsAllGood(
const std::vector<BaseStatusSignal *> &signals)
424 for (
auto signal : signals)
426 if (!signal->GetStatus().IsOK()) {
439 static bool IsAllGood(
const std::array<BaseStatusSignal *, N> &signals)
441 for (
auto signal : signals)
443 if (!signal->GetStatus().IsOK()) {
465 template <
typename... Signals,
typename = std::enable_if_t<is_all_status_signal_v<Signals...>>>
468 return SetUpdateFrequencyForAll(frequencyHz, std::array<
BaseStatusSignal *,
sizeof...(Signals)>{(&signals)...});
485 static ctre::phoenix::StatusCode
SetUpdateFrequencyForAll(units::frequency::hertz_t frequencyHz,
const std::vector<BaseStatusSignal *> &signals)
487 return Status_SetUpdateFrequencyForAll(signals.data(), signals.size(), frequencyHz.to<
double>(), 0.050);
505 static ctre::phoenix::StatusCode
SetUpdateFrequencyForAll(units::frequency::hertz_t frequencyHz,
const std::array<BaseStatusSignal *, N> &signals)
507 return Status_SetUpdateFrequencyForAll(signals.data(), signals.size(), frequencyHz.to<
double>(), 0.050);
523 virtual ctre::phoenix::StatusCode
SetUpdateFrequency(units::frequency::hertz_t frequencyHz, units::time::second_t timeoutSeconds = 50_ms) = 0;
541 const std::string &
GetName()
const {
return signalName; }
547 const std::string &
GetUnits()
const {
return units; }
571 ctre::phoenix::StatusCode
GetStatus()
const {
return error; }
584 auto const ×tamp = GetAllTimestamps().GetSystemTimestamp();
585 if (timestamp.IsValid())
588 if (_lastTimestamp != timestamp.GetTime())
590 _lastTimestamp = timestamp.GetTime();
601 template <
typename L>
627 template <
typename T>
630 bool _containsUnderlyingTypes;
631 std::map<int, StatusSignal<T>> _basicTypeMap;
634 void RefreshSwitch(
bool block, units::time::second_t timeout)
637 if (!_containsUnderlyingTypes)
642 ctre::phoenix::StatusCode outputError = Status_Get(
643 this->deviceIdentifier.network.c_str(),
644 this->deviceIdentifier.deviceHash,
646 block, timeout.to<
double>(),
648 nullptr,
nullptr,
nullptr);
652 this->error = outputError;
656 auto foundValue = _basicTypeMap.find(
static_cast<int>(switchValue));
657 if (foundValue != _basicTypeMap.end())
660 foundValue->second.RefreshValue(block, timeout,
false);
664 std::lock_guard<std::mutex> lock{_copyLck};
665 CopyFrom(foundValue->second);
675 void RefreshNoSwitch(
bool block, units::time::second_t timeout)
678 if (_containsUnderlyingTypes)
682 double outHwTimestamp;
683 double outSwTimestamp;
684 double outEcuTimestamp;
686 ctre::phoenix::StatusCode outputError = Status_Get(
687 this->deviceIdentifier.network.c_str(),
688 this->deviceIdentifier.deviceHash,
690 block, timeout.to<
double>(),
692 &outHwTimestamp, &outSwTimestamp, &outEcuTimestamp);
695 if (outputError >= 0)
697 this->timestamps.Update(
Timestamp{units::time::second_t{outSwTimestamp}, Timestamp::TimestampSource::System},
699 Timestamp{units::time::second_t{outEcuTimestamp}, Timestamp::TimestampSource::Device, outEcuTimestamp != 0.0});
701 this->error = outputError;
704 void RefreshValue(
bool block, units::time::second_t timeout,
bool ReportOnError)
706 _checkFirmVersFunction();
707 if (_containsUnderlyingTypes)
709 RefreshSwitch(block, timeout);
713 RefreshNoSwitch(block, timeout);
716 if (ReportOnError && !(this->error.IsOK()))
718 std::stringstream location;
719 location << this->deviceIdentifier.ToString() <<
" Status Signal " << this->signalName;
727 _containsUnderlyingTypes{
false},
733 StatusSignal(hardware::DeviceIdentifier deviceIdentifier,
735 std::function<
void()> checkFirmVersFunction,
736 std::string signalName) : BaseStatusSignal{std::move(deviceIdentifier), spn, std::move(signalName), std::move(checkFirmVersFunction)},
737 _containsUnderlyingTypes{false},
742 StatusSignal(hardware::DeviceIdentifier deviceIdentifier,
744 std::function<
void()> checkFirmVersFunction,
745 std::function<std::map<
int, StatusSignal<T>>()> map_filler,
746 std::string signalName) : BaseStatusSignal{std::move(deviceIdentifier), spn, std::move(signalName), std::move(checkFirmVersFunction)},
747 _containsUnderlyingTypes{true},
748 _basicTypeMap{map_filler()}
753 StatusSignal(ctre::phoenix::StatusCode error) : BaseStatusSignal{error},
754 _containsUnderlyingTypes{false},
765 if constexpr(units::traits::is_unit_t_v<T>)
777 std::stringstream ss;
792 if constexpr(units::traits::is_unit_t_v<T>)
794 return units::make_unit<T>(this->baseValue);
798 return static_cast<T
>(this->baseValue);
819 RefreshValue(
false, 0_s, ReportOnError);
836 RefreshValue(
true, timeoutSec, ReportOnError);
853 ctre::phoenix::StatusCode
SetUpdateFrequency(units::frequency::hertz_t frequencyHz, units::time::second_t timeoutSeconds = 50_ms)
override
855 if (_containsUnderlyingTypes)
857 return _basicTypeMap.begin()->second.SetUpdateFrequency(frequencyHz, timeoutSeconds);
861 return Status_SetUpdateFrequency(this->deviceIdentifier.network.c_str(),
862 this->deviceIdentifier.deviceHash,
864 frequencyHz.to<
double>(),
865 timeoutSeconds.to<
double>());
880 if (_containsUnderlyingTypes)
882 return _basicTypeMap.begin()->second.GetAppliedUpdateFrequency();
886 return units::frequency::hertz_t{
887 Status_GetAppliedUpdateFrequency(this->deviceIdentifier.network.c_str(),
888 this->deviceIdentifier.deviceHash,
904 toRet.
value = GetValue();
905 toRet.
status = GetStatus();
906 toRet.
units = GetUnits();
907 toRet.
timestamp = GetTimestamp().GetTime();
919 {
return this->Refresh().GetValue(); };
CTREXPORT void c_ctre_phoenix_report_error(int isError, int32_t errorCode, int isLVCode, const char *details, const char *location, const char *callStack)
@ OK
No Error.
Definition: StatusCodes.h:1192
@ InvalidModeToGetSignal
The current mode of the device is invalid for getting this signal.
Definition: StatusCodes.h:1840
@ InvalidNetwork
InvalidNetwork.
Definition: StatusCodes.h:1789
@ InvalidParamValue
An invalid argument was passed into the function/VI, such as a null pointer.
Definition: StatusCodes.h:1525
@ SigNotUpdated
No new response to update signal.
Definition: StatusCodes.h:1575
A collection of timestamps for a received signal.
Definition: Timestamp.hpp:132
Class that provides operations to retrieve information about a status signal.
Definition: StatusSignal.hpp:42
std::string signalName
Definition: StatusSignal.hpp:52
void CopyFrom(const BaseStatusSignal &other)
Definition: StatusSignal.hpp:61
units::time::second_t _lastTimestamp
Definition: StatusSignal.hpp:56
virtual ctre::phoenix::StatusCode SetUpdateFrequency(units::frequency::hertz_t frequencyHz, units::time::second_t timeoutSeconds=50_ms)=0
Sets the rate at which the device will publish this signal.
const AllTimestamps & GetAllTimestamps() const
Get the timestamps of this signals.
Definition: StatusSignal.hpp:559
AllTimestamps timestamps
Definition: StatusSignal.hpp:49
ctre::phoenix::StatusCode error
Definition: StatusSignal.hpp:51
static ctre::phoenix::StatusCode WaitForAll(units::time::second_t timeoutSeconds, const std::vector< BaseStatusSignal * > &signals)
Waits for new data on all provided signals up to timeout.
Definition: StatusSignal.hpp:269
static ctre::phoenix::StatusCode Status_WaitForAll(BaseStatusSignal *const *signals, size_t count, const char *network, double timeoutSeconds)
Wait for multiple signals to arrive.
static ctre::phoenix::StatusCode Status_Get(const char *network, int deviceHash, uint32_t signal, bool bWaitForUpdate, double timeoutSeconds, double *outValue, double *hwtimestamp, double *swtimestamp, double *ecutimestamp)
Get signal update.
uint16_t spn
Definition: StatusSignal.hpp:47
static ctre::phoenix::StatusCode SetUpdateFrequencyForAll(units::frequency::hertz_t frequencyHz, Signals &... signals)
Sets the update frequency of all specified status signals to the provided common frequency.
Definition: StatusSignal.hpp:466
static std::string Status_GetUnits(uint32_t signal)
Gets signal units.
static bool IsAllGood(Signals &... signals)
Checks if all signals have an OK error code.
Definition: StatusSignal.hpp:412
static ctre::phoenix::StatusCode RefreshAll(const std::array< BaseStatusSignal *, N > &signals)
Performs a non-blocking refresh on all provided signals.
Definition: StatusSignal.hpp:357
static ctre::phoenix::StatusCode RefreshAll(Signals &... signals)
Performs a non-blocking refresh on all provided signals.
Definition: StatusSignal.hpp:320
std::string units
Definition: StatusSignal.hpp:48
static bool IsAllGood(const std::vector< BaseStatusSignal * > &signals)
Checks if all signals have an OK error code.
Definition: StatusSignal.hpp:422
static double Status_GetAppliedUpdateFrequency(const char *canbus, uint32_t deviceHash, uint16_t spn)
ctre::phoenix::StatusCode GetStatus() const
Get the error code from when we last received this signal.
Definition: StatusSignal.hpp:571
static ctre::phoenix::StatusCode WaitForAllImpl(const char *location, units::time::second_t timeoutSeconds, const Arr &signals)
Implementation of the WaitForAll API.
Definition: StatusSignal.hpp:151
static ctre::phoenix::StatusCode SetUpdateFrequencyForAll(units::frequency::hertz_t frequencyHz, const std::array< BaseStatusSignal *, N > &signals)
Sets the update frequency of all specified status signals to the provided common frequency.
Definition: StatusSignal.hpp:505
static U GetLatencyCompensatedValue(StatusSignal< U > &signal, StatusSignal< U_PER_SEC > &signalSlope, units::time::second_t maxLatencySeconds=0.300_s)
Performs latency compensation on signal using the signalSlope and signal's latency to determine the m...
Definition: StatusSignal.hpp:387
virtual units::frequency::hertz_t GetAppliedUpdateFrequency() const =0
Gets the rate at which the device will publish this signal.
std::function< void()> _checkFirmVersFunction
Definition: StatusSignal.hpp:54
bool HasUpdated()
Check whether the signal has been updated since the last check.
Definition: StatusSignal.hpp:580
static ctre::phoenix::StatusCode SetUpdateFrequencyForAll(units::frequency::hertz_t frequencyHz, const std::vector< BaseStatusSignal * > &signals)
Sets the update frequency of all specified status signals to the provided common frequency.
Definition: StatusSignal.hpp:485
BaseStatusSignal(ctre::phoenix::StatusCode error)
Definition: StatusSignal.hpp:83
const std::string & GetUnits() const
Gets the units for this signal.
Definition: StatusSignal.hpp:547
static ctre::phoenix::StatusCode WaitForAll(units::time::second_t timeoutSeconds, Signals &... signals)
Waits for new data on all provided signals up to timeout.
Definition: StatusSignal.hpp:241
static ctre::phoenix::StatusCode Status_SetUpdateFrequency(const char *canbus, uint32_t deviceHash, uint16_t spn, double frequencyHz, double timeoutSeconds)
static bool IsAllGood(const std::array< BaseStatusSignal *, N > &signals)
Checks if all signals have an OK error code.
Definition: StatusSignal.hpp:439
double baseValue
Definition: StatusSignal.hpp:50
const std::string & GetName() const
Gets the name of this signal.
Definition: StatusSignal.hpp:541
virtual ~BaseStatusSignal()=0
double GetValueAsDouble() const
Gets the value of this signal as a double.
Definition: StatusSignal.hpp:553
hardware::DeviceIdentifier deviceIdentifier
Definition: StatusSignal.hpp:46
static ctre::phoenix::StatusCode Status_SetUpdateFrequencyForAll(BaseStatusSignal *const *signals, size_t count, double frequencyHz, double timeoutSeconds)
static ctre::phoenix::StatusCode WaitForAll(units::time::second_t timeoutSeconds, const std::array< BaseStatusSignal *, N > &signals)
Waits for new data on all provided signals up to timeout.
Definition: StatusSignal.hpp:299
const Timestamp & GetTimestamp() const
Get the best timestamp available to this signal.
Definition: StatusSignal.hpp:565
BaseStatusSignal(hardware::DeviceIdentifier deviceIdentifier, uint16_t spn, std::string signalName, std::function< void()> checkFirmVersFunction)
Definition: StatusSignal.hpp:70
static ctre::phoenix::StatusCode RefreshAll(const std::vector< BaseStatusSignal * > &signals)
Performs a non-blocking refresh on all provided signals.
Definition: StatusSignal.hpp:337
Represents a status signal with data of type T, and operations available to retrieve information abou...
Definition: StatusSignal.hpp:629
friend std::ostream & operator<<(std::ostream &os, const StatusSignal< T > &data)
Definition: StatusSignal.hpp:760
std::string ToString() const
Definition: StatusSignal.hpp:775
T GetValue() const
Gets the cached value from this status signal.
Definition: StatusSignal.hpp:790
virtual units::frequency::hertz_t GetAppliedUpdateFrequency() const override
Gets the rate at which the device will publish this signal.
Definition: StatusSignal.hpp:878
StatusSignal< T > & Refresh(bool ReportOnError=true)
Refreshes the value of this status signal.
Definition: StatusSignal.hpp:817
ctre::phoenix::StatusCode SetUpdateFrequency(units::frequency::hertz_t frequencyHz, units::time::second_t timeoutSeconds=50_ms) override
Sets the rate at which the device will publish this signal.
Definition: StatusSignal.hpp:853
SignalMeasurement< T > GetDataCopy() const
Get a basic data-only container with this information, to be used for things such as data logging.
Definition: StatusSignal.hpp:901
std::function< T()> AsSupplier()
Returns a lambda that calls Refresh and GetValue on this object.
Definition: StatusSignal.hpp:916
StatusSignal< T > & WaitForUpdate(units::time::second_t timeoutSec, bool ReportOnError=true)
Waits up to timeoutSec to get the up-to-date status signal value.
Definition: StatusSignal.hpp:834
Information about the timestamp of a signal.
Definition: Timestamp.hpp:20
units::time::second_t GetLatency() const
Get the latency of this timestamp compared to now.
Definition: Timestamp.hpp:114
Definition: DeviceIdentifier.hpp:19
Parent class for all devices.
Definition: ParentDevice.hpp:29
Definition: string_util.hpp:15
Type trait to verify that all types passed in are subclasses of BaseStatusSignal.
Definition: StatusSignal.hpp:206
Information from a single measurement of a status signal.
Definition: StatusSignal.hpp:603
std::string units
Units that correspond to this point.
Definition: StatusSignal.hpp:619
units::time::second_t timestamp
Timestamp of when the data point was taken.
Definition: StatusSignal.hpp:611
L value
The value of the signal, this may be an enum so it is stored as a string.
Definition: StatusSignal.hpp:607
ctre::phoenix::StatusCode status
Status code response of getting the data.
Definition: StatusSignal.hpp:615