WPILibC++ 2027.0.0-alpha-5
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 TYPE_STRING = "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 = DEFAULT_PUB_SUB_OPTIONS) {
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 = DEFAULT_PUB_SUB_OPTIONS) {
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]]
370 const PubSubOptions& options = DEFAULT_PUB_SUB_OPTIONS) {
372 m_handle, NT_DOUBLE, "double",
373 wpi::util::json::object("unit", T{}.name()), options)};
374 }
375
376 /**
377 * Create a new publisher to the topic, with type string and initial
378 * properties.
379 *
380 * The publisher is only active as long as the returned object
381 * is not destroyed.
382 *
383 * @note It is not possible to publish two different data types to the same
384 * topic. Conflicts between publishers are typically resolved by the
385 * server on a first-come, first-served basis. Any published values that
386 * do not match the topic's data type are dropped (ignored). To determine
387 * if the data type matches, use the appropriate Topic functions.
388 *
389 * @param typeString type string
390 * @param properties JSON properties
391 * @param options publish options
392 * @return publisher
393 */
394 [[nodiscard]]
396 std::string_view typeString, const wpi::util::json& properties,
397 const PubSubOptions& options = DEFAULT_PUB_SUB_OPTIONS) {
398 wpi::util::json props = properties;
399 props["unit"] = T{}.name();
400 return UnitPublisher<T>{
401 ::wpi::nt::PublishEx(m_handle, NT_DOUBLE, typeString, props, options)};
402 }
403
404 /**
405 * Create a new entry for the topic.
406 *
407 * Entries act as a combination of a subscriber and a weak publisher. The
408 * subscriber is active as long as the entry is not destroyed. The publisher
409 * is created when the entry is first written to, and remains active until
410 * either Unpublish() is called or the entry is destroyed.
411 *
412 * @note It is not possible to use two different data types with the same
413 * topic. Conflicts between publishers are typically resolved by the
414 * server on a first-come, first-served basis. Any published values that
415 * do not match the topic's data type are dropped (ignored), and the entry
416 * will show no new values if the data type does not match. To determine
417 * if the data type matches, use the appropriate Topic functions.
418 *
419 * @param defaultValue default value used when a default is not provided to a
420 * getter function
421 * @param options publish and/or subscribe options
422 * @return entry
423 */
424 [[nodiscard]]
426 const PubSubOptions& options = DEFAULT_PUB_SUB_OPTIONS) {
427 return UnitEntry<T>{
428 ::wpi::nt::GetEntry(m_handle, NT_DOUBLE, "double", options),
429 defaultValue};
430 }
431
432 /**
433 * Create a new entry for the topic, with specific type string.
434 *
435 * Entries act as a combination of a subscriber and a weak publisher. The
436 * subscriber is active as long as the entry is not destroyed. The publisher
437 * is created when the entry is first written to, and remains active until
438 * either Unpublish() is called or the entry is destroyed.
439 *
440 * @note It is not possible to use two different data types with the same
441 * topic. Conflicts between publishers are typically resolved by the
442 * server on a first-come, first-served basis. Any published values that
443 * do not match the topic's data type are dropped (ignored), and the entry
444 * will show no new values if the data type does not match. To determine
445 * if the data type matches, use the appropriate Topic functions.
446 *
447 * @param typeString type string
448 * @param defaultValue default value used when a default is not provided to a
449 * getter function
450 * @param options publish and/or subscribe options
451 * @return entry
452 */
453 [[nodiscard]]
454 EntryType GetEntryEx(std::string_view typeString, ParamType defaultValue,
455 const PubSubOptions& options = DEFAULT_PUB_SUB_OPTIONS) {
456 return UnitEntry<T>{
457 ::wpi::nt::GetEntry(m_handle, NT_DOUBLE, typeString, options),
458 defaultValue};
459 }
460};
461
462} // namespace wpi::nt
Publisher(const Publisher &)=delete
NT_Publisher m_pubHandle
NetworkTables handle.
Definition Topic.hpp:443
Subscriber(const Subscriber &)=delete
NT_Subscriber m_subHandle
Definition Topic.hpp:388
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:319
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
static constexpr std::string_view TYPE_STRING
The default type string for this topic type.
Definition UnitTopic.hpp:279
SubscriberType SubscribeEx(std::string_view typeString, ParamType defaultValue, const PubSubOptions &options=DEFAULT_PUB_SUB_OPTIONS)
Create a new subscriber to the topic, with specific type string.
Definition UnitTopic.hpp:345
UnitPublisher< T > PublisherType
Definition UnitTopic.hpp:273
UnitEntry< T > EntryType
Definition UnitTopic.hpp:274
EntryType GetEntryEx(std::string_view typeString, ParamType defaultValue, const PubSubOptions &options=DEFAULT_PUB_SUB_OPTIONS)
Create a new entry for the topic, with specific type string.
Definition UnitTopic.hpp:454
PublisherType Publish(const PubSubOptions &options=DEFAULT_PUB_SUB_OPTIONS)
Create a new publisher to the topic.
Definition UnitTopic.hpp:369
EntryType GetEntry(ParamType defaultValue, const PubSubOptions &options=DEFAULT_PUB_SUB_OPTIONS)
Create a new entry for the topic.
Definition UnitTopic.hpp:425
TimestampedUnit< T > TimestampedValueType
Definition UnitTopic.hpp:277
SubscriberType Subscribe(ParamType defaultValue, const PubSubOptions &options=DEFAULT_PUB_SUB_OPTIONS)
Create a new subscriber to the topic.
Definition UnitTopic.hpp:320
T ValueType
Definition UnitTopic.hpp:275
PublisherType PublishEx(std::string_view typeString, const wpi::util::json &properties, const PubSubOptions &options=DEFAULT_PUB_SUB_OPTIONS)
Create a new publisher to the topic, with type string and initial properties.
Definition UnitTopic.hpp:395
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
Definition json.hpp:85
static json object(Args &&... args)
Definition json.hpp:347
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 DEFAULT_PUB_SUB_OPTIONS
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.
NT_Subscriber Subscribe(NT_Topic topic, NT_Type type, std::string_view typeStr, const PubSubOptions &options=DEFAULT_PUB_SUB_OPTIONS)
Creates a new subscriber to value changes on a topic.
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=DEFAULT_PUB_SUB_OPTIONS)
Creates a new publisher to 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