WPILibC++ 2027.0.0-alpha-4
Loading...
Searching...
No Matches
UnitTopic.hpp
Go to the documentation of this file.
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#pragma once
6
7#include <stdint.h>
8
9#include <string_view>
10#include <vector>
11
12#include "wpi/nt/Topic.hpp"
13#include "wpi/nt/ntcore_cpp.hpp"
14#include "wpi/util/json.hpp"
15
16namespace wpi::nt {
17
18template <typename T>
19class UnitTopic;
20
21/**
22 * Timestamped unit.
23 *
24 * @tparam T unit type, e.g. wpi::units::meter_t
25 */
26template <typename T>
28 TimestampedUnit() = default;
31
32 /**
33 * Time in local time base.
34 */
35 int64_t time = 0;
36
37 /**
38 * Time in server time base. May be 0 or 1 for locally set values.
39 */
40 int64_t serverTime = 0;
41
42 /**
43 * Value.
44 */
45 T value = {};
46};
47
48/**
49 * NetworkTables unit-typed subscriber.
50 *
51 * @tparam T unit type, e.g. wpi::units::meter_t
52 */
53template <typename T>
54class UnitSubscriber : public Subscriber {
55 public:
57 using ValueType = T;
58 using ParamType = T;
60
61 UnitSubscriber() = default;
62
63 /**
64 * Construct from a subscriber handle; recommended to use
65 * UnitTopic::Subscribe() instead.
66 *
67 * @param handle Native handle
68 * @param defaultValue Default value
69 */
71 : Subscriber{handle}, m_defaultValue{defaultValue} {}
72
73 /**
74 * Get the last published value.
75 * If no value has been published, returns the stored default value.
76 *
77 * @return value
78 */
79 ValueType Get() const { return Get(m_defaultValue); }
80
81 /**
82 * Get the last published value.
83 * If no value has been published, returns the passed defaultValue.
84 *
85 * @param defaultValue default value to return if no value has been published
86 * @return value
87 */
88 ValueType Get(ParamType defaultValue) const {
89 return T{::wpi::nt::GetDouble(m_subHandle, defaultValue.value())};
90 }
91
92 /**
93 * Get the last published value along with its timestamp
94 * If no value has been published, returns the stored default value and a
95 * timestamp of 0.
96 *
97 * @return timestamped value
98 */
99 TimestampedValueType GetAtomic() const { return GetAtomic(m_defaultValue); }
100
101 /**
102 * Get the last published value along with its timestamp.
103 * If no value has been published, returns the passed defaultValue and a
104 * timestamp of 0.
105 *
106 * @param defaultValue default value to return if no value has been published
107 * @return timestamped value
108 */
110 auto doubleVal =
111 ::wpi::nt::GetAtomicDouble(m_subHandle, defaultValue.value());
112 return {doubleVal.time, doubleVal.serverTime, doubleVal.value};
113 }
114
115 /**
116 * Get an array of all value changes since the last call to ReadQueue.
117 * Also provides a timestamp for each value.
118 *
119 * @note The "poll storage" subscribe option can be used to set the queue
120 * depth.
121 *
122 * @return Array of timestamped values; empty array if no new changes have
123 * been published since the previous call.
124 */
125 std::vector<TimestampedValueType> ReadQueue() {
126 std::vector<TimestampedUnit<T>> vals;
127 auto doubleVals = ::wpi::nt::ReadQueueDouble(m_subHandle);
128 vals.reserve(doubleVals.size());
129 for (auto&& val : doubleVals) {
130 vals.emplace_back(val.time, val.serverTime, val.value);
131 }
132 }
133
134 /**
135 * Get the corresponding topic.
136 *
137 * @return Topic
138 */
142
143 private:
144 ValueType m_defaultValue;
145};
146
147/**
148 * NetworkTables unit-typed publisher.
149 *
150 * @tparam T unit type, e.g. wpi::units::meter_t
151 */
152template <typename T>
153class UnitPublisher : public Publisher {
154 public:
156 using ValueType = T;
157 using ParamType = T;
158
160
161 UnitPublisher() = default;
162
163 /**
164 * Construct from a publisher handle; recommended to use
165 * UnitTopic::Publish() instead.
166 *
167 * @param handle Native handle
168 */
169 explicit UnitPublisher(NT_Publisher handle) : Publisher{handle} {}
170
171 /**
172 * Publish a new value.
173 *
174 * @param value value to publish
175 * @param time timestamp; 0 indicates current NT time should be used
176 */
177 void Set(ParamType value, int64_t time = 0) {
178 ::wpi::nt::SetDouble(m_pubHandle, value.value(), time);
179 }
180
181 /**
182 * Publish a default value.
183 * On reconnect, a default value will never be used in preference to a
184 * published value.
185 *
186 * @param value value
187 */
188 void SetDefault(ParamType value) {
190 }
191
192 /**
193 * Get the corresponding topic.
194 *
195 * @return Topic
196 */
200};
201
202/**
203 * NetworkTables unit-typed entry.
204 *
205 * @note Unlike NetworkTableEntry, the entry goes away when this is destroyed.
206 *
207 * @tparam T unit type, e.g. wpi::units::meter_t
208 */
209template <typename T>
210class UnitEntry final : public UnitSubscriber<T>, public UnitPublisher<T> {
211 public:
215 using ValueType = T;
216 using ParamType = T;
217
219
220 UnitEntry() = default;
221
222 /**
223 * Construct from an entry handle; recommended to use
224 * UnitTopic::GetEntry() instead.
225 *
226 * @param handle Native handle
227 * @param defaultValue Default value
228 */
229 UnitEntry(NT_Entry handle, ParamType defaultValue)
230 : UnitSubscriber<T>{handle, defaultValue}, UnitPublisher<T>{handle} {}
231
232 /**
233 * Determines if the native handle is valid.
234 *
235 * @return True if the native handle is valid, false otherwise.
236 */
237 explicit operator bool() const { return this->m_subHandle != 0; }
238
239 /**
240 * Gets the native handle for the entry.
241 *
242 * @return Native handle
243 */
244 NT_Entry GetHandle() const { return this->m_subHandle; }
245
246 /**
247 * Get the corresponding topic.
248 *
249 * @return Topic
250 */
254
255 /**
256 * Stops publishing the entry if it's published.
257 */
259};
260
261/**
262 * NetworkTables unit-typed topic. Publishers publish the type name (e.g.
263 * "meter") as the "unit" property. Type conversions are not performed--for
264 * correct behavior the publisher and subscriber must use the same unit type,
265 * but this can be checked at runtime using IsMatchingUnit().
266 *
267 * @tparam T unit type, e.g. wpi::units::meter_t
268 */
269template <typename T>
270class UnitTopic final : public Topic {
271 public:
275 using ValueType = T;
276 using ParamType = T;
278 /** The default type string for this topic type. */
279 static constexpr std::string_view kTypeString = "double";
280
281 UnitTopic() = default;
282
283 /**
284 * Construct from a topic handle.
285 *
286 * @param handle Native handle
287 */
288 explicit UnitTopic(NT_Topic handle) : Topic{handle} {}
289
290 /**
291 * Construct from a generic topic.
292 *
293 * @param topic Topic
294 */
295 explicit UnitTopic(Topic topic) : Topic{topic} {}
296
297 /**
298 * Verify the topic has a matching unit type (if the topic is published).
299 *
300 * @return True if unit matches, false if not matching or topic not published.
301 */
302 bool IsMatchingUnit() const { return GetProperty("unit") == T{}.name(); }
303
304 /**
305 * Create a new subscriber to the topic.
306 *
307 * <p>The subscriber is only active as long as the returned object
308 * is not destroyed.
309 *
310 * @note Subscribers that do not match the published data type do not return
311 * any values. To determine if the data type matches, use the appropriate
312 * Topic functions.
313 *
314 * @param defaultValue default value used when a default is not provided to a
315 * getter function
316 * @param options subscribe options
317 * @return subscriber
318 */
319 [[nodiscard]]
321 ParamType defaultValue,
322 const PubSubOptions& options = kDefaultPubSubOptions) {
323 return UnitSubscriber<T>{
324 ::wpi::nt::Subscribe(m_handle, NT_DOUBLE, "double", options),
325 defaultValue};
326 }
327
328 /**
329 * Create a new subscriber to the topic, with specific type string.
330 *
331 * <p>The subscriber is only active as long as the returned object
332 * is not destroyed.
333 *
334 * @note Subscribers that do not match the published data type do not return
335 * any values. To determine if the data type matches, use the appropriate
336 * Topic functions.
337 *
338 * @param typeString type string
339 * @param defaultValue default value used when a default is not provided to a
340 * getter function
341 * @param options subscribe options
342 * @return subscriber
343 */
344 [[nodiscard]]
346 std::string_view typeString, ParamType defaultValue,
347 const PubSubOptions& options = kDefaultPubSubOptions) {
348 return UnitSubscriber<T>{
349 ::wpi::nt::Subscribe(m_handle, NT_DOUBLE, typeString, options),
350 defaultValue};
351 }
352
353 /**
354 * Create a new publisher to the topic.
355 *
356 * The publisher is only active as long as the returned object
357 * is not destroyed.
358 *
359 * @note It is not possible to publish two different data types to the same
360 * topic. Conflicts between publishers are typically resolved by the
361 * server on a first-come, first-served basis. Any published values that
362 * do not match the topic's data type are dropped (ignored). To determine
363 * if the data type matches, use the appropriate Topic functions.
364 *
365 * @param options publish options
366 * @return publisher
367 */
368 [[nodiscard]]
371 m_handle, NT_DOUBLE, "double", {{"unit", T{}.name()}}, options)};
372 }
373
374 /**
375 * Create a new publisher to the topic, with type string and initial
376 * properties.
377 *
378 * The publisher is only active as long as the returned object
379 * is not destroyed.
380 *
381 * @note It is not possible to publish two different data types to the same
382 * topic. Conflicts between publishers are typically resolved by the
383 * server on a first-come, first-served basis. Any published values that
384 * do not match the topic's data type are dropped (ignored). To determine
385 * if the data type matches, use the appropriate Topic functions.
386 *
387 * @param typeString type string
388 * @param properties JSON properties
389 * @param options publish options
390 * @return publisher
391 */
392 [[nodiscard]]
394 std::string_view typeString, const wpi::util::json& properties,
395 const PubSubOptions& options = kDefaultPubSubOptions) {
396 wpi::util::json props = properties;
397 props["unit"] = T{}.name();
398 return UnitPublisher<T>{
399 ::wpi::nt::PublishEx(m_handle, NT_DOUBLE, typeString, props, options)};
400 }
401
402 /**
403 * Create a new entry for the topic.
404 *
405 * Entries act as a combination of a subscriber and a weak publisher. The
406 * subscriber is active as long as the entry is not destroyed. The publisher
407 * is created when the entry is first written to, and remains active until
408 * either Unpublish() is called or the entry is destroyed.
409 *
410 * @note It is not possible to use two different data types with the same
411 * topic. Conflicts between publishers are typically resolved by the
412 * server on a first-come, first-served basis. Any published values that
413 * do not match the topic's data type are dropped (ignored), and the entry
414 * will show no new values if the data type does not match. To determine
415 * if the data type matches, use the appropriate Topic functions.
416 *
417 * @param defaultValue default value used when a default is not provided to a
418 * getter function
419 * @param options publish and/or subscribe options
420 * @return entry
421 */
422 [[nodiscard]]
424 const PubSubOptions& options = kDefaultPubSubOptions) {
425 return UnitEntry<T>{
426 ::wpi::nt::GetEntry(m_handle, NT_DOUBLE, "double", options),
427 defaultValue};
428 }
429
430 /**
431 * Create a new entry for the topic, with specific type string.
432 *
433 * Entries act as a combination of a subscriber and a weak publisher. The
434 * subscriber is active as long as the entry is not destroyed. The publisher
435 * is created when the entry is first written to, and remains active until
436 * either Unpublish() is called or the entry is destroyed.
437 *
438 * @note It is not possible to use two different data types with the same
439 * topic. Conflicts between publishers are typically resolved by the
440 * server on a first-come, first-served basis. Any published values that
441 * do not match the topic's data type are dropped (ignored), and the entry
442 * will show no new values if the data type does not match. To determine
443 * if the data type matches, use the appropriate Topic functions.
444 *
445 * @param typeString type string
446 * @param defaultValue default value used when a default is not provided to a
447 * getter function
448 * @param options publish and/or subscribe options
449 * @return entry
450 */
451 [[nodiscard]]
452 EntryType GetEntryEx(std::string_view typeString, ParamType defaultValue,
453 const PubSubOptions& options = kDefaultPubSubOptions) {
454 return UnitEntry<T>{
455 ::wpi::nt::GetEntry(m_handle, NT_DOUBLE, typeString, options),
456 defaultValue};
457 }
458};
459
460} // namespace wpi::nt
Publisher(const Publisher &)=delete
NT_Publisher m_pubHandle
NetworkTables handle.
Definition Topic.hpp:440
Subscriber(const Subscriber &)=delete
NT_Subscriber m_subHandle
Definition Topic.hpp:385
wpi::util::json GetProperty(std::string_view name) const
Gets the current value of a property (as a JSON object).
NT_Topic m_handle
Definition Topic.hpp:316
Topic()=default
NetworkTables unit-typed entry.
Definition UnitTopic.hpp:210
UnitSubscriber< T > SubscriberType
Definition UnitTopic.hpp:212
T ParamType
Definition UnitTopic.hpp:216
TimestampedUnit< T > TimestampedValueType
Definition UnitTopic.hpp:218
UnitEntry(NT_Entry handle, ParamType defaultValue)
Construct from an entry handle; recommended to use UnitTopic::GetEntry() instead.
Definition UnitTopic.hpp:229
UnitEntry()=default
TopicType GetTopic() const
Get the corresponding topic.
Definition UnitTopic.hpp:251
void Unpublish()
Stops publishing the entry if it's published.
Definition UnitTopic.hpp:258
UnitPublisher< T > PublisherType
Definition UnitTopic.hpp:213
T ValueType
Definition UnitTopic.hpp:215
UnitTopic< T > TopicType
Definition UnitTopic.hpp:214
NT_Entry GetHandle() const
Gets the native handle for the entry.
Definition UnitTopic.hpp:244
NetworkTables unit-typed publisher.
Definition UnitTopic.hpp:153
void SetDefault(ParamType value)
Publish a default value.
Definition UnitTopic.hpp:188
TopicType GetTopic() const
Get the corresponding topic.
Definition UnitTopic.hpp:197
TimestampedUnit< T > TimestampedValueType
Definition UnitTopic.hpp:159
void Set(ParamType value, int64_t time=0)
Publish a new value.
Definition UnitTopic.hpp:177
UnitTopic< T > TopicType
Definition UnitTopic.hpp:155
UnitPublisher(NT_Publisher handle)
Construct from a publisher handle; recommended to use UnitTopic::Publish() instead.
Definition UnitTopic.hpp:169
T ValueType
Definition UnitTopic.hpp:156
T ParamType
Definition UnitTopic.hpp:157
NetworkTables unit-typed subscriber.
Definition UnitTopic.hpp:54
TimestampedValueType GetAtomic() const
Get the last published value along with its timestamp If no value has been published,...
Definition UnitTopic.hpp:99
std::vector< TimestampedValueType > ReadQueue()
Get an array of all value changes since the last call to ReadQueue.
Definition UnitTopic.hpp:125
UnitTopic< T > TopicType
Definition UnitTopic.hpp:56
T ParamType
Definition UnitTopic.hpp:58
ValueType Get() const
Get the last published value.
Definition UnitTopic.hpp:79
TimestampedValueType GetAtomic(ParamType defaultValue) const
Get the last published value along with its timestamp.
Definition UnitTopic.hpp:109
TopicType GetTopic() const
Get the corresponding topic.
Definition UnitTopic.hpp:139
TimestampedUnit< T > TimestampedValueType
Definition UnitTopic.hpp:59
UnitSubscriber(NT_Subscriber handle, ParamType defaultValue)
Construct from a subscriber handle; recommended to use UnitTopic::Subscribe() instead.
Definition UnitTopic.hpp:70
T ValueType
Definition UnitTopic.hpp:57
ValueType Get(ParamType defaultValue) const
Get the last published value.
Definition UnitTopic.hpp:88
NetworkTables unit-typed topic.
Definition UnitTopic.hpp:270
UnitPublisher< T > PublisherType
Definition UnitTopic.hpp:273
UnitEntry< T > EntryType
Definition UnitTopic.hpp:274
EntryType GetEntry(ParamType defaultValue, const PubSubOptions &options=kDefaultPubSubOptions)
Create a new entry for the topic.
Definition UnitTopic.hpp:423
static constexpr std::string_view kTypeString
The default type string for this topic type.
Definition UnitTopic.hpp:279
PublisherType Publish(const PubSubOptions &options=kDefaultPubSubOptions)
Create a new publisher to the topic.
Definition UnitTopic.hpp:369
EntryType GetEntryEx(std::string_view typeString, ParamType defaultValue, const PubSubOptions &options=kDefaultPubSubOptions)
Create a new entry for the topic, with specific type string.
Definition UnitTopic.hpp:452
TimestampedUnit< T > TimestampedValueType
Definition UnitTopic.hpp:277
PublisherType PublishEx(std::string_view typeString, const wpi::util::json &properties, const PubSubOptions &options=kDefaultPubSubOptions)
Create a new publisher to the topic, with type string and initial properties.
Definition UnitTopic.hpp:393
T ValueType
Definition UnitTopic.hpp:275
SubscriberType SubscribeEx(std::string_view typeString, ParamType defaultValue, const PubSubOptions &options=kDefaultPubSubOptions)
Create a new subscriber to the topic, with specific type string.
Definition UnitTopic.hpp:345
SubscriberType Subscribe(ParamType defaultValue, const PubSubOptions &options=kDefaultPubSubOptions)
Create a new subscriber to the topic.
Definition UnitTopic.hpp:320
UnitTopic(Topic topic)
Construct from a generic topic.
Definition UnitTopic.hpp:295
T ParamType
Definition UnitTopic.hpp:276
UnitSubscriber< T > SubscriberType
Definition UnitTopic.hpp:272
bool IsMatchingUnit() const
Verify the topic has a matching unit type (if the topic is published).
Definition UnitTopic.hpp:302
UnitTopic(NT_Topic handle)
Construct from a topic handle.
Definition UnitTopic.hpp:288
bool SetDefaultDouble(NT_Handle pubentry, double defaultValue)
Publish a default value.
bool SetDouble(NT_Handle pubentry, double value, int64_t time=0)
Publish a new value.
std::vector< TimestampedDouble > ReadQueueDouble(NT_Handle subentry)
Get an array of all value changes since the last call to ReadQueue.
double GetDouble(NT_Handle subentry, double defaultValue)
Get the last published value.
TimestampedDouble GetAtomicDouble(NT_Handle subentry, double defaultValue)
Get the last published value along with its timestamp.
NT_Handle NT_Topic
Definition ntcore_c.h:42
NT_Handle NT_Subscriber
Definition ntcore_c.h:43
NT_Handle NT_Publisher
Definition ntcore_c.h:44
NT_Handle NT_Entry
Definition ntcore_c.h:37
@ NT_DOUBLE
Definition ntcore_c.h:53
constexpr PubSubOptions kDefaultPubSubOptions
Default publish/subscribe options.
Definition ntcore_cpp.hpp:388
NT_Entry GetEntry(NT_Inst inst, std::string_view name)
Get Entry Handle.
NT_Topic GetTopicFromHandle(NT_Handle pubsubentry)
Gets the topic handle from an entry/subscriber/publisher handle.
void Unpublish(NT_Handle pubentry)
Stops publisher.
NT_Publisher PublishEx(NT_Topic topic, NT_Type type, std::string_view typeStr, const wpi::util::json &properties, const PubSubOptions &options=kDefaultPubSubOptions)
Creates a new publisher to a topic.
NT_Subscriber Subscribe(NT_Topic topic, NT_Type type, std::string_view typeStr, const PubSubOptions &options=kDefaultPubSubOptions)
Creates a new subscriber to value changes on a topic.
NetworkTables (ntcore) namespace.
Definition NTSendable.hpp:9
NetworkTables publish/subscribe options.
Definition ntcore_cpp.hpp:303
Timestamped unit.
Definition UnitTopic.hpp:27
int64_t time
Time in local time base.
Definition UnitTopic.hpp:35
int64_t serverTime
Time in server time base.
Definition UnitTopic.hpp:40
T value
Value.
Definition UnitTopic.hpp:45
TimestampedUnit(int64_t time, int64_t serverTime, T value)
Definition UnitTopic.hpp:29