17#include <initializer_list>
22#include <units/base.h>
23#include <units/frequency.h>
24#include <units/time.h>
62 this->units = other.
units;
65 this->error = other.
error;
72 std::function<
void()> checkFirmVersFunction) :
104 double timeoutSeconds);
106 static ctre::phoenix::StatusCode
Status_SetUpdateFrequency(
const char *canbus, uint32_t deviceHash, uint16_t spn,
double frequencyHz,
double timeoutSeconds);
136 bool bWaitForUpdate,
double timeoutSeconds,
138 double *hwtimestamp,
double *swtimestamp,
double *ecutimestamp);
149 template <
typename Arr>
150 static ctre::phoenix::StatusCode
WaitForAllImpl(
const char *location, units::time::second_t timeoutSeconds,
const Arr &signals)
152 if (signals.size() < 1)
157 retval.GetDescription(),
162 const std::string &network = signals[0]->deviceIdentifier.network;
164 for (
auto signal : signals)
167 if (network != signal->deviceIdentifier.network)
172 retval.GetDescription(),
180 for (
auto signal : signals)
182 signal->_checkFirmVersFunction();
186 ctre::phoenix::StatusCode retval = Status_WaitForAll(signals.data(), signals.size(), network.c_str(), timeoutSeconds.to<
double>());
189 if (
false == retval.IsOK())
192 retval.GetDescription(),
202 template <
typename... Signals>
204 std::conjunction<std::is_base_of<BaseStatusSignal, std::remove_reference_t<Signals>>...>
210 template <
typename... Signals>
239 template <
typename... Signals,
typename = std::enable_if_t<is_all_status_signal_v<Signals...>>>
240 static ctre::phoenix::StatusCode
WaitForAll(units::time::second_t timeoutSeconds, Signals &... signals)
242 return WaitForAll(timeoutSeconds,
268 static ctre::phoenix::StatusCode
WaitForAll(units::time::second_t timeoutSeconds,
const std::vector<BaseStatusSignal *> &signals)
271 constexpr char kLocation[] =
"ctre::phoenix6::BaseStatusSignal::WaitForAll";
272 return WaitForAllImpl(kLocation, timeoutSeconds, signals);
298 static ctre::phoenix::StatusCode
WaitForAll(units::time::second_t timeoutSeconds,
const std::array<BaseStatusSignal *, N> &signals)
301 constexpr char kLocation[] =
"ctre::phoenix6::BaseStatusSignal::WaitForAll";
302 return WaitForAllImpl(kLocation, timeoutSeconds, signals);
318 template <
typename... Signals,
typename = std::enable_if_t<is_all_status_signal_v<Signals...>>>
319 static ctre::phoenix::StatusCode
RefreshAll(Signals &... signals)
321 return RefreshAll(std::array<
BaseStatusSignal *,
sizeof...(Signals)>{(&signals)...});
336 static ctre::phoenix::StatusCode
RefreshAll(
const std::vector<BaseStatusSignal *> &signals)
339 constexpr char kLocation[] =
"ctre::phoenix6::BaseStatusSignal::RefreshAll";
340 return WaitForAllImpl(kLocation, 0_s, signals);
356 static ctre::phoenix::StatusCode
RefreshAll(
const std::array<BaseStatusSignal *, N> &signals)
359 constexpr char kLocation[] =
"ctre::phoenix6::BaseStatusSignal::RefreshAll";
360 return WaitForAllImpl(kLocation, 0_s, signals);
385 template <
typename U,
typename U_PER_SEC>
388 static_assert(units::traits::is_unit_t_v<U>,
"signal must be a unit signal");
389 static_assert(units::traits::is_unit_t_v<U_PER_SEC>,
"signalSlope must be a unit signal");
390 using lhs =
typename units::traits::unit_t_traits<U>::unit_type;
391 using rhs =
typename units::traits::unit_t_traits<U_PER_SEC>::unit_type;
392 static_assert(units::traits::is_convertible_unit_v<lhs, units::compound_unit<rhs, units::seconds>>,
393 "Compensation can only be performed on a signal with its derivative");
395 const U nonCompensatedSignal = signal.
GetValue();
396 const U_PER_SEC changeInSignal = signalSlope.
GetValue();
398 if (maxLatencySeconds > 0_s && latency > maxLatencySeconds) {
399 latency = maxLatencySeconds;
401 return nonCompensatedSignal + (changeInSignal * latency);
410 template <
typename... Signals,
typename = std::enable_if_t<is_all_status_signal_v<Signals...>>>
413 return IsAllGood(std::array<
BaseStatusSignal *,
sizeof...(Signals)>{(&signals)...});
421 static bool IsAllGood(
const std::vector<BaseStatusSignal *> &signals)
423 for (
auto signal : signals)
425 if (!signal->GetStatus().IsOK()) {
438 static bool IsAllGood(
const std::array<BaseStatusSignal *, N> &signals)
440 for (
auto signal : signals)
442 if (!signal->GetStatus().IsOK()) {
464 template <
typename... Signals,
typename = std::enable_if_t<is_all_status_signal_v<Signals...>>>
467 return SetUpdateFrequencyForAll(frequencyHz, std::array<
BaseStatusSignal *,
sizeof...(Signals)>{(&signals)...});
484 static ctre::phoenix::StatusCode
SetUpdateFrequencyForAll(units::frequency::hertz_t frequencyHz,
const std::vector<BaseStatusSignal *> &signals)
486 return Status_SetUpdateFrequencyForAll(signals.data(), signals.size(), frequencyHz.to<
double>(), 0.050);
504 static ctre::phoenix::StatusCode
SetUpdateFrequencyForAll(units::frequency::hertz_t frequencyHz,
const std::array<BaseStatusSignal *, N> &signals)
506 return Status_SetUpdateFrequencyForAll(signals.data(), signals.size(), frequencyHz.to<
double>(), 0.050);
522 virtual ctre::phoenix::StatusCode
SetUpdateFrequency(units::frequency::hertz_t frequencyHz, units::time::second_t timeoutSeconds = 50_ms) = 0;
540 const std::string &
GetName()
const {
return signalName; }
546 const std::string &
GetUnits()
const {
return units; }
570 ctre::phoenix::StatusCode
GetStatus()
const {
return error; }
583 auto const ×tamp = GetAllTimestamps().GetSystemTimestamp();
584 if (timestamp.IsValid())
587 if (_lastTimestamp != timestamp.GetTime())
589 _lastTimestamp = timestamp.GetTime();
600 template <
typename L>
626 template <
typename T>
629 bool _containsUnderlyingTypes;
630 std::map<int, StatusSignal<T>> _basicTypeMap;
632 void RefreshSwitch(
bool block, units::time::second_t timeout)
635 if (!_containsUnderlyingTypes)
640 ctre::phoenix::StatusCode outputError = Status_Get(
641 this->deviceIdentifier.network.c_str(),
642 this->deviceIdentifier.deviceHash,
644 block, timeout.to<
double>(),
646 nullptr,
nullptr,
nullptr);
650 this->error = outputError;
654 auto foundValue = _basicTypeMap.find(
static_cast<int>(switchValue));
655 if (foundValue != _basicTypeMap.end())
658 foundValue->second.RefreshValue(block, timeout,
false);
659 CopyFrom(foundValue->second);
668 void RefreshNoSwitch(
bool block, units::time::second_t timeout)
671 if (_containsUnderlyingTypes)
675 double outHwTimestamp;
676 double outSwTimestamp;
677 double outEcuTimestamp;
679 ctre::phoenix::StatusCode outputError = Status_Get(
680 this->deviceIdentifier.network.c_str(),
681 this->deviceIdentifier.deviceHash,
683 block, timeout.to<
double>(),
685 &outHwTimestamp, &outSwTimestamp, &outEcuTimestamp);
688 if (outputError >= 0)
690 this->timestamps.Update(
Timestamp{units::time::second_t{outSwTimestamp}, Timestamp::TimestampSource::System},
692 Timestamp{units::time::second_t{outEcuTimestamp}, Timestamp::TimestampSource::Device, outEcuTimestamp != 0.0});
694 this->error = outputError;
697 void RefreshValue(
bool block, units::time::second_t timeout,
bool ReportOnError)
699 _checkFirmVersFunction();
700 if (_containsUnderlyingTypes)
702 RefreshSwitch(block, timeout);
706 RefreshNoSwitch(block, timeout);
709 if (ReportOnError && !(this->error.IsOK()))
711 std::stringstream location;
712 location << this->deviceIdentifier.ToString() <<
" Status Signal " << this->signalName;
720 _containsUnderlyingTypes{
false},
726 StatusSignal(hardware::DeviceIdentifier deviceIdentifier,
728 std::function<
void()> checkFirmVersFunction,
729 std::string signalName) : BaseStatusSignal{std::move(deviceIdentifier), spn, std::move(signalName), std::move(checkFirmVersFunction)},
730 _containsUnderlyingTypes{false},
735 StatusSignal(hardware::DeviceIdentifier deviceIdentifier,
737 std::function<
void()> checkFirmVersFunction,
738 std::function<std::map<
int, StatusSignal<T>>()> map_filler,
739 std::string signalName) : BaseStatusSignal{std::move(deviceIdentifier), spn, std::move(signalName), std::move(checkFirmVersFunction)},
740 _containsUnderlyingTypes{true},
741 _basicTypeMap{map_filler()}
746 StatusSignal(ctre::phoenix::StatusCode error) : BaseStatusSignal{error},
747 _containsUnderlyingTypes{false},
758 if constexpr(units::traits::is_unit_t_v<T>)
770 std::stringstream ss;
785 if constexpr(units::traits::is_unit_t_v<T>)
787 return units::make_unit<T>(this->baseValue);
791 return static_cast<T
>(this->baseValue);
812 RefreshValue(
false, 0_s, ReportOnError);
829 RefreshValue(
true, timeoutSec, ReportOnError);
846 ctre::phoenix::StatusCode
SetUpdateFrequency(units::frequency::hertz_t frequencyHz, units::time::second_t timeoutSeconds = 50_ms)
override
848 if (_containsUnderlyingTypes)
850 return _basicTypeMap.begin()->second.SetUpdateFrequency(frequencyHz, timeoutSeconds);
854 return Status_SetUpdateFrequency(this->deviceIdentifier.network.c_str(),
855 this->deviceIdentifier.deviceHash,
857 frequencyHz.to<
double>(),
858 timeoutSeconds.to<
double>());
873 if (_containsUnderlyingTypes)
875 return _basicTypeMap.begin()->second.GetAppliedUpdateFrequency();
879 return units::frequency::hertz_t{
880 Status_GetAppliedUpdateFrequency(this->deviceIdentifier.network.c_str(),
881 this->deviceIdentifier.deviceHash,
897 toRet.
value = GetValue();
898 toRet.
status = GetStatus();
899 toRet.
units = GetUnits();
900 toRet.
timestamp = GetTimestamp().GetTime();
912 {
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:1196
@ InvalidModeToGetSignal
The current mode of the device is invalid for getting this signal.
Definition: StatusCodes.h:1844
@ InvalidNetwork
InvalidNetwork.
Definition: StatusCodes.h:1793
@ InvalidParamValue
An invalid argument was passed into the function/VI, such as a null pointer.
Definition: StatusCodes.h:1529
@ SigNotUpdated
No new response to update signal.
Definition: StatusCodes.h:1579
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:41
std::string signalName
Definition: StatusSignal.hpp:51
void CopyFrom(const BaseStatusSignal &other)
Definition: StatusSignal.hpp:60
units::time::second_t _lastTimestamp
Definition: StatusSignal.hpp:55
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:558
AllTimestamps timestamps
Definition: StatusSignal.hpp:48
ctre::phoenix::StatusCode error
Definition: StatusSignal.hpp:50
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:268
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:46
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:465
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:411
static ctre::phoenix::StatusCode RefreshAll(const std::array< BaseStatusSignal *, N > &signals)
Performs a non-blocking refresh on all provided signals.
Definition: StatusSignal.hpp:356
static ctre::phoenix::StatusCode RefreshAll(Signals &... signals)
Performs a non-blocking refresh on all provided signals.
Definition: StatusSignal.hpp:319
std::string units
Definition: StatusSignal.hpp:47
static bool IsAllGood(const std::vector< BaseStatusSignal * > &signals)
Checks if all signals have an OK error code.
Definition: StatusSignal.hpp:421
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:570
static ctre::phoenix::StatusCode WaitForAllImpl(const char *location, units::time::second_t timeoutSeconds, const Arr &signals)
Implementation of the WaitForAll API.
Definition: StatusSignal.hpp:150
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:504
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:386
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:53
bool HasUpdated()
Check whether the signal has been updated since the last check.
Definition: StatusSignal.hpp:579
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:484
BaseStatusSignal(ctre::phoenix::StatusCode error)
Definition: StatusSignal.hpp:82
const std::string & GetUnits() const
Gets the units for this signal.
Definition: StatusSignal.hpp:546
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:240
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:438
double baseValue
Definition: StatusSignal.hpp:49
const std::string & GetName() const
Gets the name of this signal.
Definition: StatusSignal.hpp:540
virtual ~BaseStatusSignal()=0
double GetValueAsDouble() const
Gets the value of this signal as a double.
Definition: StatusSignal.hpp:552
hardware::DeviceIdentifier deviceIdentifier
Definition: StatusSignal.hpp:45
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:298
const Timestamp & GetTimestamp() const
Get the best timestamp available to this signal.
Definition: StatusSignal.hpp:564
BaseStatusSignal(hardware::DeviceIdentifier deviceIdentifier, uint16_t spn, std::string signalName, std::function< void()> checkFirmVersFunction)
Definition: StatusSignal.hpp:69
static ctre::phoenix::StatusCode RefreshAll(const std::vector< BaseStatusSignal * > &signals)
Performs a non-blocking refresh on all provided signals.
Definition: StatusSignal.hpp:336
Represents a status signal with data of type T, and operations available to retrieve information abou...
Definition: StatusSignal.hpp:628
friend std::ostream & operator<<(std::ostream &os, const StatusSignal< T > &data)
Definition: StatusSignal.hpp:753
std::string ToString() const
Definition: StatusSignal.hpp:768
T GetValue() const
Gets the cached value from this status signal.
Definition: StatusSignal.hpp:783
virtual units::frequency::hertz_t GetAppliedUpdateFrequency() const override
Gets the rate at which the device will publish this signal.
Definition: StatusSignal.hpp:871
StatusSignal< T > & Refresh(bool ReportOnError=true)
Refreshes the value of this status signal.
Definition: StatusSignal.hpp:810
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:846
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:894
std::function< T()> AsSupplier()
Returns a lambda that calls Refresh and GetValue on this object.
Definition: StatusSignal.hpp:909
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:827
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:205
Information from a single measurement of a status signal.
Definition: StatusSignal.hpp:602
std::string units
Units that correspond to this point.
Definition: StatusSignal.hpp:618
units::time::second_t timestamp
Timestamp of when the data point was taken.
Definition: StatusSignal.hpp:610
L value
The value of the signal, this may be an enum so it is stored as a string.
Definition: StatusSignal.hpp:606
ctre::phoenix::StatusCode status
Status code response of getting the data.
Definition: StatusSignal.hpp:614