CTRE Phoenix Pro C++ 23.0.12
StatusSignalValue.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) Cross The Road Electronics.  All rights reserved.
3 * License information can be found in CTRE_LICENSE.txt
4 * For support and suggestions contact support@ctr-electronics.com or file
5 * an issue tracker at https://github.com/CrossTheRoadElec/Phoenix-Releases
6 */
7#pragma once
8
15#include <functional>
16#include <initializer_list>
17#include <map>
18#include <ostream>
19#include <sstream>
20#include <string>
21#include <units/base.h>
22#include <units/frequency.h>
23#include <units/time.h>
24
25#if defined(_WIN32) || defined(_WIN64)
26#include <Windows.h> // For UTF-8 support
27#endif
28
29namespace ctre {
30namespace phoenixpro {
31
32 namespace hardware {
33 class ParentDevice;
34 }
35
36 template <typename T>
37 class StatusSignalValue;
38
40 {
41 friend hardware::ParentDevice; // Allow ParentDevice to set error
42
43 protected:
45 uint16_t spn;
46 std::string units;
49 double baseValue = 0;
51 std::string signalName;
52
53 template <typename T>
54 friend class StatusSignalValue;
55
57 {
58 this->units = other.units;
59 this->timestamps = other.timestamps;
60 this->timestampType = other.timestampType;
61 this->baseValue = other.baseValue;
62 this->error = other.error;
63 // We don't care about copying the signal name, because the user will expect the original name
64 }
65
67 uint16_t spn,
68 std::string signalName) : deviceIdentifier{std::move(deviceIdentifier)},
69 spn{spn},
70 signalName{std::move(signalName)}
71 {
72 }
73
74 /* Constructor for an invalid BaseStatusSignalValue */
75 BaseStatusSignalValue(ctre::phoenix::StatusCode error) : deviceIdentifier{hardware::DeviceIdentifier{}},
76 spn{0},
77 error{error},
78 signalName{"Invalid"}
79 {
80 }
81
82 /**
83 * \brief Wait for multiple signals to arrive
84 *
85 * \param signals Signals to wait for
86 * \param network Network to wait for the signals on
87 * \param timeoutSeconds Maximum time to wait for all these signals
88 * \returns Status of the wait
89 */
90 static ctre::phoenix::StatusCode Status_WaitForAll(
91 std::initializer_list<BaseStatusSignalValue *> signals,
92 const char *network,
93 units::time::second_t timeoutSeconds);
94
95 /**
96 * \brief Wait for multiple signals to arrive
97 *
98 * \param signals Signals to wait for
99 * \param network Network to wait for the signals on
100 * \param timeoutSeconds Maximum time to wait for all these signals
101 * \returns Status of the wait
102 */
103 static ctre::phoenix::StatusCode Status_WaitForAll(
104 const std::vector<BaseStatusSignalValue *> &signals,
105 const char *network,
106 units::time::second_t timeoutSeconds);
107
108 ctre::phoenix::StatusCode SetUpdateFrequency(const char *canbus, uint32_t deviceHash, uint16_t spn, units::frequency::hertz_t frequencyHz, units::time::second_t timeoutSeconds);
109
110 /**
111 * Get signal update. Caller either get last received, or wait for an update.
112 *
113 * \param network Name of bus (can, canfd, canivore-name, future protocols)
114 * \param deviceHash Hash id of the device (based on device id and model)
115 * \param signal Signal to get
116 * \param bWaitForUpdate If true, API will wait up to timeoutSeconds for an update. If false, routine will poll last received and use timeoutSeconds to return error code if too old.
117 * \param timeoutSeconds How long to wait or how old the signal can be before error'ing
118 * \param outValue Value of the signal
119 * \param units Unit that corresponds with signal
120 * \param hwtimestamp Timestamp of the signal
121 * \param swtimestamp Timestamp of the signal
122 * \param ecutimestamp Timestamp of the signal
123 * \param timestampType Which type of timestamp was gotten
124 * \returns Status of the get
125 */
126 static ctre::phoenix::StatusCode Status_Get(
127 const char *network,
128 int deviceHash,
129 uint32_t signal,
130 bool bWaitForUpdate, units::time::second_t timeoutSeconds,
131 double *outValue, std::string *units,
132 double *hwtimestamp, double *swtimestamp, double *ecutimestamp, int32_t *timestampType);
133
134 public:
135 virtual ~BaseStatusSignalValue() = 0; // Declare virtual destructor to make this class abstract
136
137 /**
138 * \brief Wait for all provided signals up to timeout.
139 * This API is typically used with CANivore Bus signals as they will be synced using the
140 * CANivore Timesync feature and arrive simultaneously. Signals on a roboRIO bus cannot
141 * be synced and may require a significantly longer blocking call to receive all signals.
142 *
143 * This can also be used with a timeout of zero to refresh many signals at once, which
144 * is faster than calling Refresh() on every signal.
145 *
146 * \param timeoutSeconds How long to wait for all the signals to arrive.
147 * Pass zero to just refresh all signals without blocking.
148 * \param signals Signals to wait on, passed as initializer list of signal addresses.
149 * \return An InvalidParamValue if signals array is empty,
150 * InvalidNetwork if signals are on different CAN bus networks,
151 * RxTimeout if it took longer than timeoutSeconds to receive all the signals.
152 * An OK status code means that all signals arrived within timeoutSeconds and they are all OK.
153 *
154 * Any other value represents the StatusCode of the first failed signal.
155 * Call GetError() on each signal to determine which ones failed.
156 */
157 static ctre::phoenix::StatusCode WaitForAll(units::time::second_t timeoutSeconds, std::initializer_list<BaseStatusSignalValue *> signals)
158 {
159 return WaitForAll(timeoutSeconds,
160 std::vector<BaseStatusSignalValue*>(signals.begin(), signals.end()));
161 }
162 /**
163 * \brief Wait for all provided signals up to timeout.
164 * This API is typically used with CANivore Bus signals as they will be synced using the
165 * CANivore Timesync feature and arrive simultaneously. Signals on a roboRIO bus cannot
166 * be synced and may require a significantly longer blocking call to receive all signals.
167 *
168 * This can also be used with a timeout of zero to refresh many signals at once, which
169 * is faster than calling Refresh() on every signal.
170 *
171 * \param timeoutSeconds How long to wait for all the signals to arrive.
172 * Pass zero to just refresh all signals without blocking.
173 * \param signals Signals to wait on, passed as vector of signal addresses.
174 * \return An InvalidParamValue if signals array is empty,
175 * InvalidNetwork if signals are on different CAN bus networks,
176 * RxTimeout if it took longer than timeoutSeconds to receive all the signals.
177 * An OK status code means that all signals arrived within timeoutSeconds and they are all OK.
178 *
179 * Any other value represents the StatusCode of the first failed signal.
180 * Call GetError() on each signal to determine which ones failed.
181 */
182 static ctre::phoenix::StatusCode WaitForAll(units::time::second_t timeoutSeconds, const std::vector<BaseStatusSignalValue *> &signals)
183 {
184 /* static string for location */
185 const char kLocation[] = "ctre::phoenixpro::BaseStatusSignalValue::WaitForAll";
186
187 if (signals.size() < 1)
188 {
189 /* We don't have any signals to wait for, so return early */
190 ctre::phoenix::StatusCode retval = ctre::phoenix::StatusCode::InvalidParamValue;
191 c_ctre_phoenix_report_error(true, retval, 0,
192 retval.GetDescription(),
193 kLocation,
195 return retval;
196 }
197 const std::string &network = (*signals.begin())->deviceIdentifier.network;
198
199 for (auto signal : signals)
200 {
201 /* Check that they all have the same network */
202 if (network != signal->deviceIdentifier.network)
203 {
204 ctre::phoenix::StatusCode retval = ctre::phoenix::StatusCode::InvalidNetwork; // Networks don't match, return early
205
206 c_ctre_phoenix_report_error(true, retval, 0,
207 retval.GetDescription(),
208 kLocation,
210 return retval;
211 }
212 }
213 /* Now wait for all the signals */
214 ctre::phoenix::StatusCode retval = Status_WaitForAll(signals, network.c_str(), timeoutSeconds);
215
216 /*error reporting */
217 if (false == retval.IsOK())
218 {
219 c_ctre_phoenix_report_error(retval.IsError(), retval, 0,
220 retval.GetDescription(),
221 kLocation,
223 }
224 return retval;
225 }
226 /**
227 * \brief Performs latency compensation on signal using the signalSlope and signal's latency to determine
228 * the magnitude of compensation. The caller must refresh these StatusSignalValues beforehand,
229 * this function only does the math required for latency compensation.
230 *
231 * \example units::turn_t compensatedTurns = GetLatencyCompensatedValue(fx.GetPosition(), fx.GetVelocity());
232 *
233 * \tparam U Type of signal's underlying type. This is the type that the function will return.
234 * \tparam U_PER_SEC Type of signalSlope's underlying type. This must be the derivative of U.
235 * \param signal Signal to be latency compensated. Caller must make sure this signal is up to date
236 * either by calling \c Refresh() or \c WaitForUpdate().
237 * \param signalSlope Derivative of signal that informs compensation magnitude. Caller must make sure this
238 * signal is up to date either by calling \c Refresh() or \c WaitForUpdate().
239 * \returns Latency compensated value from the signal StatusSignalValue.
240 */
241 template <typename U, typename U_PER_SEC>
243 {
244 static_assert(units::traits::is_unit_t_v<U>, "signal must be a unit signal");
245 static_assert(units::traits::is_unit_t_v<U_PER_SEC>, "signalSlope must be a unit signal");
246 using lhs = typename units::traits::unit_t_traits<U>::unit_type;
247 using rhs = typename units::traits::unit_t_traits<U_PER_SEC>::unit_type;
248 static_assert(units::traits::is_convertible_unit_v<lhs, units::compound_unit<rhs, units::seconds>>,
249 "Compensation can only be performed on a signal with its derivative");
250 U nonCompensatedSignal = signal.GetValue();
251 U_PER_SEC changeInSignal = signalSlope.GetValue();
252 units::second_t latency = signal.GetTimestamp().GetLatency();
253 return nonCompensatedSignal + (changeInSignal * latency);
254 }
255 /**
256 * \brief Check if all signals have an OK error code
257 *
258 * \param signals Signals to check error code of.
259 * \returns True if all signals are OK, false otherwise
260 */
261 static ctre::phoenix::StatusCode IsAllGood(std::initializer_list<BaseStatusSignalValue *> signals)
262 {
263 for (auto signal : signals)
264 {
265 if (signal->GetError() != ctre::phoenix::StatusCode::OK)
266 return false;
267 }
268 return true;
269 }
270
271 /**
272 * \brief Gets the units for this signal
273 *
274 * \returns String representation of units for this signal
275 */
276 const std::string &GetUnits() const { return units; }
277 /**
278 * \brief Get the timestamps of this signals
279 *
280 * \returns All timestamps for this signal
281 */
282 const AllTimestamps &GetAllTimestamps() const { return timestamps; }
283 /**
284 * \brief Get the best timestamp available to this signal
285 *
286 * \returns Best available timestamp for this signal
287 */
289 /**
290 * \brief Get the error code from when we last received this signal
291 *
292 * \returns Last cached Error Code
293 */
294 ctre::phoenix::StatusCode GetError() const { return error; }
295 };
296
297 template <typename L>
299 {
300 /**
301 * \brief The value of the signal, this may be an enum so it is stored as a string
302 */
304 /**
305 * \brief Timestamp of when the data point was taken
306 */
307 units::time::second_t timestamp;
308 /**
309 * \brief Code response of getting the data
310 */
311 ctre::phoenix::StatusCode error;
312 /**
313 * \brief Units that correspond to this point
314 */
315 std::string units;
316 };
317
318 template <typename T>
320 {
321 bool _containsUnderlyingTypes;
322 std::map<int, StatusSignalValue<T>> _basicTypeMap;
323 std::function<void()> _checkFirmVersFunction;
325
326 void RefreshSwitch(bool block, units::time::second_t timeout)
327 {
328 /* Just make sure we don't do anything if we're not a switching statement */
329 if (!_containsUnderlyingTypes)
330 return;
331
332 double switchValue;
333 /* We only care about the switch value, so get that quickly */
334 ctre::phoenix::StatusCode outputError = Status_Get(
335 this->deviceIdentifier.network.c_str(),
336 this->deviceIdentifier.deviceHash,
337 this->spn,
338 block, timeout,
339 &switchValue, nullptr,
340 nullptr, nullptr, nullptr, nullptr);
341
342 if (outputError != ctre::phoenix::StatusCode::OK)
343 {
344 this->error = outputError;
345 return;
346 }
347
348 auto foundValue = _basicTypeMap.find(static_cast<int>(switchValue));
349 if (foundValue != _basicTypeMap.end())
350 {
351 /* Found it, so refresh it and set our values to it */
352 foundValue->second.RefreshValue(block, timeout, false); // Top-level refresh will handle the error
353
354 /* save to members, use locks because string copies are not atomic */
355 {
356 std::lock_guard<std::mutex> lock{_copyLck};
357 CopyFrom(foundValue->second);
358 }
359 }
360 else
361 {
362 /* Didn't find it, so set our error */
364 }
365 }
366
367 void RefreshNoSwitch(bool block, units::time::second_t timeout)
368 {
369 /* Just make sure we don't do anything if we are a switching statement */
370 if (_containsUnderlyingTypes)
371 return;
372
373 /* fetch values */
374 std::string outUnits;
375 double outHwTimestamp;
376 double outSwTimestamp;
377 double outEcuTimestamp;
378 int32_t outTimestampType;
379
380 ctre::phoenix::StatusCode outputError = Status_Get(
381 this->deviceIdentifier.network.c_str(),
382 this->deviceIdentifier.deviceHash,
383 this->spn,
384 block, timeout,
385 &this->baseValue, &outUnits,
386 &outHwTimestamp, &outSwTimestamp, &outEcuTimestamp, &outTimestampType);
387
388 /* save to members, use locks if need be (remember though Java locks are not reliable) */
389 if (outputError >= 0)
390 {
391 this->timestamps.Update(Timestamp{units::time::second_t{outSwTimestamp}, Timestamp::TimestampSource::System},
392 Timestamp{units::time::second_t{outHwTimestamp}, Timestamp::TimestampSource::CANivore},
393 Timestamp{});
394 }
395 this->units = outUnits; // Units are always correct since they're independent of CAN frame
396 this->error = outputError;
397 }
398
399 void RefreshValue(bool block, units::time::second_t timeout, bool ReportOnError)
400 {
401 _checkFirmVersFunction();
402 if (_containsUnderlyingTypes)
403 {
404 RefreshSwitch(block, timeout);
405 }
406 else
407 {
408 RefreshNoSwitch(block, timeout);
409 }
410
411 if (ReportOnError && !(this->error.IsOK()))
412 {
413 std::stringstream location;
414 location << this->deviceIdentifier.ToString() << " StatusSignalValue " << this->signalName;
415 c_ctre_phoenix_report_error(this->error.IsError(), this->error, 0, this->error.GetDescription(), location.str().c_str(), ctre::phoenix::platform::GetStackTrace(1).c_str());
416 }
417 }
418
420
422 _containsUnderlyingTypes{false},
423 _basicTypeMap{},
424 _checkFirmVersFunction{[] {}}
425 {
426 CopyFrom(other);
427 }
428
429 StatusSignalValue(hardware::DeviceIdentifier deviceIdentifier,
430 uint16_t spn,
431 std::function<void()> checkFirmVersFunction,
432 std::string signalName) : BaseStatusSignalValue{std::move(deviceIdentifier), spn, std::move(signalName)},
433 _containsUnderlyingTypes{false},
434 _basicTypeMap{},
435 _checkFirmVersFunction{checkFirmVersFunction}
436 {
437 }
438
439 StatusSignalValue(hardware::DeviceIdentifier deviceIdentifier,
440 uint16_t spn,
441 std::function<void()> checkFirmVersFunction,
442 std::function<std::map<int, StatusSignalValue<T>>()> map_filler,
443 std::string signalName) : BaseStatusSignalValue{std::move(deviceIdentifier), spn, std::move(signalName)},
444 _containsUnderlyingTypes{true},
445 _basicTypeMap{map_filler()},
446 _checkFirmVersFunction{checkFirmVersFunction}
447 {
448 }
449
450 /* Constructor for an invalid StatusSignalValue */
451 StatusSignalValue(ctre::phoenix::StatusCode error) : BaseStatusSignalValue{error},
452 _containsUnderlyingTypes{false},
453 _basicTypeMap{},
454 _checkFirmVersFunction{[] {}}
455 {
456 }
457
458 public:
459 friend std::ostream &operator<<(std::ostream &os, const StatusSignalValue<T> &data)
460 {
461 #if defined(_WIN32) || defined(_WIN64)
462 // Set console code page to UTF-8 so console known how to interpret string data
463 SetConsoleOutputCP(CP_UTF8);
464 #endif
465 if constexpr(units::traits::is_unit_t_v<T>)
466 {
467 os << data.GetValue().value() << " " << data.GetUnits();
468 }
469 else
470 {
471 os << data.GetValue() << " " << data.GetUnits();
472 }
473 return os;
474 }
475 std::string ToString() const
476 {
477 std::stringstream ss;
478 ss << *this;
479 return ss.str();
480 }
481
482 /**
483 * \brief Gets the cached value from this status signal value
484 *
485 * \details Gets the cached value. To make sure the value is up-to-date
486 * call \c Refresh() or \c WaitForUpdate()
487 *
488 * \returns Cached value
489 */
490 T GetValue() const
491 {
492 if constexpr(units::traits::is_unit_t_v<T>)
493 {
494 return units::make_unit<T>(this->baseValue);
495 }
496 else
497 {
498 return static_cast<T>(this->baseValue);
499 }
500 }
501
502 /**
503 * \brief Refreshes this status signal value.
504 *
505 * If the user application caches this StatusSignalValue object
506 * instead of periodically fetching it from the hardware device,
507 * this function must be called to fetch fresh data.
508 *
509 * \details This performs a non-blocking refresh operation. If
510 * you want to wait until you receive the signal, call
511 * \c WaitForUpdate() instead.
512 *
513 * \param ReportOnError Report to the Driver Station if this refresh returns a StatusCode other than OK
514 *
515 * \returns Reference to itself
516 */
517 StatusSignalValue<T> &Refresh(bool ReportOnError = true)
518 {
519 RefreshValue(false, 0.300_s, ReportOnError); // Don't block and error if signal is older than 0.300 seconds
520 return *this;
521 }
522 /**
523 * \brief Waits up to timeoutSec to get the up-to-date status signal value
524 *
525 * \details This performs a blocking refresh operation. If
526 * you want to non-blocking refresh the signal, call
527 * \c Refresh() instead.
528 *
529 * \param timeoutSec Timeout to wait for an update on the signal
530 * \param ReportOnError Report to the Driver Station if this refresh returns a StatusCode other than OK
531 *
532 * \returns Reference to itself
533 */
534 StatusSignalValue<T> &WaitForUpdate(units::time::second_t timeoutSec, bool ReportOnError = true)
535 {
536 RefreshValue(true, timeoutSec, ReportOnError);
537 return *this;
538 }
539
540 /**
541 * \brief Get a basic data-only container with this information, to be used for things such as data logging.
542 *
543 * \returns Basic structure with all relevant information
544 */
546 {
548 toRet.value = GetValue();
549 toRet.error = GetError();
550 toRet.units = GetUnits();
551 toRet.timestamp = GetTimestamp().GetTime();
552 return toRet;
553 }
554
555 /**
556 * \brief Sets the rate at which the device will publish this signal.
557 *
558 * The minimum supported signal frequency is 4 Hz, and the maximum is 1000 Hz.
559 *
560 * \param frequencyHz Rate to publish the signal in Hz.
561 * \param timeoutSeconds Maximum amount of time to wait when performing the action
562 * \returns Status code of setting the update frequency
563 */
564 ctre::phoenix::StatusCode SetUpdateFrequency(units::frequency::hertz_t frequencyHz, units::time::second_t timeoutSeconds = 50_ms)
565 {
566 /* attempt to change the frequency */
567 return BaseStatusSignalValue::SetUpdateFrequency(this->deviceIdentifier.network.c_str(),
568 this->deviceIdentifier.deviceHash,
569 this->spn,
570 frequencyHz,
571 timeoutSeconds);
572 }
573
574 /**
575 * \brief Returns a lambda that calls Refresh and GetValue on this object. This is useful for command-based programming.
576 *
577 * \returns std::function<T()> that calls Refresh() and returns this value.
578 */
579 std::function<T()> AsSupplier()
580 {
581 return [this]()
582 { return this->Refresh().GetValue(); };
583 }
584 };
585
586}
587}
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:1101
@ InvalidModeToGetSignal
The current mode of the device is invalid for getting this signal.
Definition: StatusCodes.h:1740
@ InvalidNetwork
InvalidNetwork.
Definition: StatusCodes.h:1688
@ InvalidParamValue
Incorrect argument passed into function/VI.
Definition: StatusCodes.h:1425
@ SigNotUpdated
No new response to update signal.
Definition: StatusCodes.h:1474
A collection of timestamps for a received signal.
Definition: Timestamp.hpp:131
void Update(const Timestamp &newSystemTimestamp, const Timestamp &newCanivoreTimestamp, const Timestamp &newDeviceTimestamp)
Definition: Timestamp.hpp:137
const Timestamp & GetBestTimestamp() const
Get the best timestamp available.
Definition: Timestamp.hpp:147
Definition: StatusSignalValue.hpp:40
static ctre::phoenix::StatusCode Status_WaitForAll(std::initializer_list< BaseStatusSignalValue * > signals, const char *network, units::time::second_t timeoutSeconds)
Wait for multiple signals to arrive.
void CopyFrom(const BaseStatusSignalValue &other)
Definition: StatusSignalValue.hpp:56
static U GetLatencyCompensatedValue(StatusSignalValue< U > &signal, StatusSignalValue< U_PER_SEC > &signalSlope)
Definition: StatusSignalValue.hpp:242
int timestampType
Definition: StatusSignalValue.hpp:48
static ctre::phoenix::StatusCode IsAllGood(std::initializer_list< BaseStatusSignalValue * > signals)
Check if all signals have an OK error code.
Definition: StatusSignalValue.hpp:261
ctre::phoenix::StatusCode SetUpdateFrequency(const char *canbus, uint32_t deviceHash, uint16_t spn, units::frequency::hertz_t frequencyHz, units::time::second_t timeoutSeconds)
static ctre::phoenix::StatusCode WaitForAll(units::time::second_t timeoutSeconds, std::initializer_list< BaseStatusSignalValue * > signals)
Wait for all provided signals up to timeout.
Definition: StatusSignalValue.hpp:157
AllTimestamps timestamps
Definition: StatusSignalValue.hpp:47
const std::string & GetUnits() const
Gets the units for this signal.
Definition: StatusSignalValue.hpp:276
uint16_t spn
Definition: StatusSignalValue.hpp:45
BaseStatusSignalValue(ctre::phoenix::StatusCode error)
Definition: StatusSignalValue.hpp:75
static ctre::phoenix::StatusCode Status_WaitForAll(const std::vector< BaseStatusSignalValue * > &signals, const char *network, units::time::second_t timeoutSeconds)
Wait for multiple signals to arrive.
hardware::DeviceIdentifier deviceIdentifier
Definition: StatusSignalValue.hpp:44
const AllTimestamps & GetAllTimestamps() const
Get the timestamps of this signals.
Definition: StatusSignalValue.hpp:282
static ctre::phoenix::StatusCode Status_Get(const char *network, int deviceHash, uint32_t signal, bool bWaitForUpdate, units::time::second_t timeoutSeconds, double *outValue, std::string *units, double *hwtimestamp, double *swtimestamp, double *ecutimestamp, int32_t *timestampType)
Get signal update.
std::string units
Definition: StatusSignalValue.hpp:46
std::string signalName
Definition: StatusSignalValue.hpp:51
BaseStatusSignalValue(hardware::DeviceIdentifier deviceIdentifier, uint16_t spn, std::string signalName)
Definition: StatusSignalValue.hpp:66
const Timestamp & GetTimestamp() const
Get the best timestamp available to this signal.
Definition: StatusSignalValue.hpp:288
ctre::phoenix::StatusCode error
Definition: StatusSignalValue.hpp:50
static ctre::phoenix::StatusCode WaitForAll(units::time::second_t timeoutSeconds, const std::vector< BaseStatusSignalValue * > &signals)
Wait for all provided signals up to timeout.
Definition: StatusSignalValue.hpp:182
double baseValue
Definition: StatusSignalValue.hpp:49
ctre::phoenix::StatusCode GetError() const
Get the error code from when we last received this signal.
Definition: StatusSignalValue.hpp:294
friend class StatusSignalValue
Definition: StatusSignalValue.hpp:54
Definition: StatusSignalValue.hpp:320
StatusSignalValue< T > & Refresh(bool ReportOnError=true)
Refreshes this status signal value.
Definition: StatusSignalValue.hpp:517
StatusSignalValue< T > & WaitForUpdate(units::time::second_t timeoutSec, bool ReportOnError=true)
Waits up to timeoutSec to get the up-to-date status signal value.
Definition: StatusSignalValue.hpp:534
std::function< T()> AsSupplier()
Returns a lambda that calls Refresh and GetValue on this object.
Definition: StatusSignalValue.hpp:579
T GetValue() const
Gets the cached value from this status signal value.
Definition: StatusSignalValue.hpp:490
friend std::ostream & operator<<(std::ostream &os, const StatusSignalValue< T > &data)
Definition: StatusSignalValue.hpp:459
std::string ToString() const
Definition: StatusSignalValue.hpp:475
ctre::phoenix::StatusCode SetUpdateFrequency(units::frequency::hertz_t frequencyHz, units::time::second_t timeoutSeconds=50_ms)
Sets the rate at which the device will publish this signal.
Definition: StatusSignalValue.hpp:564
SignalMeasurement< T > GetDataCopy() const
Get a basic data-only container with this information, to be used for things such as data logging.
Definition: StatusSignalValue.hpp:545
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:113
@ CANivore
Timestamp as reported by the CANivore.
@ System
Timestamp as reported by the system.
Definition: DeviceIdentifier.hpp:19
std::string network
Definition: DeviceIdentifier.hpp:21
std::string ToString() const
Definition: DeviceIdentifier.hpp:34
Parent class for all devices.
Definition: ParentDevice.hpp:30
CTREXPORT std::string GetStackTrace(int offset)
Get a stack trace, ignoring the first "offset" symbols.
Definition: string_util.hpp:14
Definition: StatusSignalValue.hpp:299
ctre::phoenix::StatusCode error
Code response of getting the data.
Definition: StatusSignalValue.hpp:311
units::time::second_t timestamp
Timestamp of when the data point was taken.
Definition: StatusSignalValue.hpp:307
std::string units
Units that correspond to this point.
Definition: StatusSignalValue.hpp:315
L value
The value of the signal, this may be an enum so it is stored as a string.
Definition: StatusSignalValue.hpp:303