WPILibC++ 2025.2.1
Loading...
Searching...
No Matches
UnitTopic.h
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/json.h>
13
14#include "networktables/Topic.h"
15#include "ntcore_cpp.h"
16
17namespace nt {
18
19template <typename T>
20class UnitTopic;
21
22/**
23 * Timestamped unit.
24 *
25 * @tparam T unit type, e.g. units::meter_t
26 */
27template <typename T>
29 TimestampedUnit() = default;
32
33 /**
34 * Time in local time base.
35 */
36 int64_t time = 0;
37
38 /**
39 * Time in server time base. May be 0 or 1 for locally set values.
40 */
41 int64_t serverTime = 0;
42
43 /**
44 * Value.
45 */
46 T value = {};
47};
48
49/**
50 * NetworkTables unit-typed subscriber.
51 *
52 * @tparam T unit type, e.g. units::meter_t
53 */
54template <typename T>
55class UnitSubscriber : public Subscriber {
56 public:
58 using ValueType = T;
59 using ParamType = T;
61
62 UnitSubscriber() = default;
63
64 /**
65 * Construct from a subscriber handle; recommended to use
66 * UnitTopic::Subscribe() instead.
67 *
68 * @param handle Native handle
69 * @param defaultValue Default value
70 */
72 : Subscriber{handle}, m_defaultValue{defaultValue} {}
73
74 /**
75 * Get the last published value.
76 * If no value has been published, returns the stored default value.
77 *
78 * @return value
79 */
80 ValueType Get() const { return Get(m_defaultValue); }
81
82 /**
83 * Get the last published value.
84 * If no value has been published, returns the passed defaultValue.
85 *
86 * @param defaultValue default value to return if no value has been published
87 * @return value
88 */
89 ValueType Get(ParamType defaultValue) const {
90 return T{::nt::GetDouble(m_subHandle, defaultValue.value())};
91 }
92
93 /**
94 * Get the last published value along with its timestamp
95 * If no value has been published, returns the stored default value and a
96 * timestamp of 0.
97 *
98 * @return timestamped value
99 */
100 TimestampedValueType GetAtomic() const { return GetAtomic(m_defaultValue); }
101
102 /**
103 * Get the last published value along with its timestamp.
104 * If no value has been published, returns the passed defaultValue and a
105 * timestamp of 0.
106 *
107 * @param defaultValue default value to return if no value has been published
108 * @return timestamped value
109 */
111 auto doubleVal = ::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 = ::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. 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 ::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) {
189 ::nt::SetDefaultDouble(m_pubHandle, value.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. 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. 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 ::nt::Subscribe(m_handle, NT_DOUBLE, "double", options), defaultValue};
325 }
326
327 /**
328 * Create a new subscriber to the topic, with specific type string.
329 *
330 * <p>The subscriber is only active as long as the returned object
331 * is not destroyed.
332 *
333 * @note Subscribers that do not match the published data type do not return
334 * any values. To determine if the data type matches, use the appropriate
335 * Topic functions.
336 *
337 * @param typeString type string
338 * @param defaultValue default value used when a default is not provided to a
339 * getter function
340 * @param options subscribe options
341 * @return subscriber
342 */
343 [[nodiscard]]
345 std::string_view typeString, ParamType defaultValue,
346 const PubSubOptions& options = kDefaultPubSubOptions) {
347 return UnitSubscriber<T>{
348 ::nt::Subscribe(m_handle, NT_DOUBLE, typeString, options),
349 defaultValue};
350 }
351
352 /**
353 * Create a new publisher to the topic.
354 *
355 * The publisher is only active as long as the returned object
356 * is not destroyed.
357 *
358 * @note It is not possible to publish two different data types to the same
359 * topic. Conflicts between publishers are typically resolved by the
360 * server on a first-come, first-served basis. Any published values that
361 * do not match the topic's data type are dropped (ignored). To determine
362 * if the data type matches, use the appropriate Topic functions.
363 *
364 * @param options publish options
365 * @return publisher
366 */
367 [[nodiscard]]
370 {{"unit", T{}.name()}}, options)};
371 }
372
373 /**
374 * Create a new publisher to the topic, with type string and initial
375 * properties.
376 *
377 * The publisher is only active as long as the returned object
378 * is not destroyed.
379 *
380 * @note It is not possible to publish two different data types to the same
381 * topic. Conflicts between publishers are typically resolved by the
382 * server on a first-come, first-served basis. Any published values that
383 * do not match the topic's data type are dropped (ignored). To determine
384 * if the data type matches, use the appropriate Topic functions.
385 *
386 * @param typeString type string
387 * @param properties JSON properties
388 * @param options publish options
389 * @return publisher
390 */
391 [[nodiscard]]
393 std::string_view typeString, const wpi::json& properties,
394 const PubSubOptions& options = kDefaultPubSubOptions) {
395 wpi::json props = properties;
396 props["unit"] = T{}.name();
397 return UnitPublisher<T>{
398 ::nt::PublishEx(m_handle, NT_DOUBLE, typeString, props, options)};
399 }
400
401 /**
402 * Create a new entry for the topic.
403 *
404 * Entries act as a combination of a subscriber and a weak publisher. The
405 * subscriber is active as long as the entry is not destroyed. The publisher
406 * is created when the entry is first written to, and remains active until
407 * either Unpublish() is called or the entry is destroyed.
408 *
409 * @note It is not possible to use two different data types with the same
410 * topic. Conflicts between publishers are typically resolved by the
411 * server on a first-come, first-served basis. Any published values that
412 * do not match the topic's data type are dropped (ignored), and the entry
413 * will show no new values if the data type does not match. To determine
414 * if the data type matches, use the appropriate Topic functions.
415 *
416 * @param defaultValue default value used when a default is not provided to a
417 * getter function
418 * @param options publish and/or subscribe options
419 * @return entry
420 */
421 [[nodiscard]]
423 const PubSubOptions& options = kDefaultPubSubOptions) {
424 return UnitEntry<T>{::nt::GetEntry(m_handle, NT_DOUBLE, "double", options),
425 defaultValue};
426 }
427
428 /**
429 * Create a new entry for the topic, with specific type string.
430 *
431 * Entries act as a combination of a subscriber and a weak publisher. The
432 * subscriber is active as long as the entry is not destroyed. The publisher
433 * is created when the entry is first written to, and remains active until
434 * either Unpublish() is called or the entry is destroyed.
435 *
436 * @note It is not possible to use two different data types with the same
437 * topic. Conflicts between publishers are typically resolved by the
438 * server on a first-come, first-served basis. Any published values that
439 * do not match the topic's data type are dropped (ignored), and the entry
440 * will show no new values if the data type does not match. To determine
441 * if the data type matches, use the appropriate Topic functions.
442 *
443 * @param typeString type string
444 * @param defaultValue default value used when a default is not provided to a
445 * getter function
446 * @param options publish and/or subscribe options
447 * @return entry
448 */
449 [[nodiscard]]
450 EntryType GetEntryEx(std::string_view typeString, ParamType defaultValue,
451 const PubSubOptions& options = kDefaultPubSubOptions) {
452 return UnitEntry<T>{
453 ::nt::GetEntry(m_handle, NT_DOUBLE, typeString, options), defaultValue};
454 }
455};
456
457} // namespace nt
NetworkTables publisher.
Definition Topic.h:393
NT_Publisher m_pubHandle
NetworkTables handle.
Definition Topic.h:441
NetworkTables subscriber.
Definition Topic.h:321
NT_Subscriber m_subHandle
Definition Topic.h:386
NetworkTables Topic.
Definition Topic.h:28
NT_Topic m_handle
Definition Topic.h:317
wpi::json GetProperty(std::string_view name) const
Gets the current value of a property (as a JSON object).
NetworkTables unit-typed entry.
Definition UnitTopic.h:210
UnitEntry()=default
void Unpublish()
Stops publishing the entry if it's published.
Definition UnitTopic.h:258
NT_Entry GetHandle() const
Gets the native handle for the entry.
Definition UnitTopic.h:244
T ParamType
Definition UnitTopic.h:216
TopicType GetTopic() const
Get the corresponding topic.
Definition UnitTopic.h:251
T ValueType
Definition UnitTopic.h:215
UnitEntry(NT_Entry handle, ParamType defaultValue)
Construct from an entry handle; recommended to use UnitTopic::GetEntry() instead.
Definition UnitTopic.h:229
NetworkTables unit-typed publisher.
Definition UnitTopic.h:153
UnitPublisher()=default
void Set(ParamType value, int64_t time=0)
Publish a new value.
Definition UnitTopic.h:177
void SetDefault(ParamType value)
Publish a default value.
Definition UnitTopic.h:188
UnitPublisher(NT_Publisher handle)
Construct from a publisher handle; recommended to use UnitTopic::Publish() instead.
Definition UnitTopic.h:169
T ParamType
Definition UnitTopic.h:157
TopicType GetTopic() const
Get the corresponding topic.
Definition UnitTopic.h:197
T ValueType
Definition UnitTopic.h:156
NetworkTables unit-typed subscriber.
Definition UnitTopic.h:55
ValueType Get() const
Get the last published value.
Definition UnitTopic.h:80
TopicType GetTopic() const
Get the corresponding topic.
Definition UnitTopic.h:139
std::vector< TimestampedValueType > ReadQueue()
Get an array of all value changes since the last call to ReadQueue.
Definition UnitTopic.h:125
TimestampedValueType GetAtomic(ParamType defaultValue) const
Get the last published value along with its timestamp.
Definition UnitTopic.h:110
UnitSubscriber()=default
T ValueType
Definition UnitTopic.h:58
ValueType Get(ParamType defaultValue) const
Get the last published value.
Definition UnitTopic.h:89
UnitSubscriber(NT_Subscriber handle, ParamType defaultValue)
Construct from a subscriber handle; recommended to use UnitTopic::Subscribe() instead.
Definition UnitTopic.h:71
TimestampedValueType GetAtomic() const
Get the last published value along with its timestamp If no value has been published,...
Definition UnitTopic.h:100
T ParamType
Definition UnitTopic.h:59
NetworkTables unit-typed topic.
Definition UnitTopic.h:270
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.h:344
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.h:450
PublisherType PublishEx(std::string_view typeString, const wpi::json &properties, const PubSubOptions &options=kDefaultPubSubOptions)
Create a new publisher to the topic, with type string and initial properties.
Definition UnitTopic.h:392
bool IsMatchingUnit() const
Verify the topic has a matching unit type (if the topic is published).
Definition UnitTopic.h:302
SubscriberType Subscribe(ParamType defaultValue, const PubSubOptions &options=kDefaultPubSubOptions)
Create a new subscriber to the topic.
Definition UnitTopic.h:320
static constexpr std::string_view kTypeString
The default type string for this topic type.
Definition UnitTopic.h:279
T ValueType
Definition UnitTopic.h:275
UnitTopic(NT_Topic handle)
Construct from a topic handle.
Definition UnitTopic.h:288
UnitTopic()=default
UnitTopic(Topic topic)
Construct from a generic topic.
Definition UnitTopic.h:295
EntryType GetEntry(ParamType defaultValue, const PubSubOptions &options=kDefaultPubSubOptions)
Create a new entry for the topic.
Definition UnitTopic.h:422
T ParamType
Definition UnitTopic.h:276
PublisherType Publish(const PubSubOptions &options=kDefaultPubSubOptions)
Create a new publisher to the topic.
Definition UnitTopic.h:368
bool SetDefaultDouble(NT_Handle pubentry, double defaultValue)
Publish a default value.
TimestampedDouble GetAtomicDouble(NT_Handle subentry, double defaultValue)
Get the last published value along with its timestamp.
double GetDouble(NT_Handle subentry, double defaultValue)
Get the last published 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.
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:56
constexpr PubSubOptions kDefaultPubSubOptions
Default publish/subscribe options.
Definition ntcore_cpp.h:390
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_Publisher PublishEx(NT_Topic topic, NT_Type type, std::string_view typeStr, const wpi::json &properties, const PubSubOptions &options=kDefaultPubSubOptions)
Creates a new publisher to a topic.
void Unpublish(NT_Handle pubentry)
Stops publisher.
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 ntcore_cpp.h:36
NetworkTables publish/subscribe options.
Definition ntcore_cpp.h:305
Timestamped unit.
Definition UnitTopic.h:28
int64_t time
Time in local time base.
Definition UnitTopic.h:36
int64_t serverTime
Time in server time base.
Definition UnitTopic.h:41
TimestampedUnit(int64_t time, int64_t serverTime, T value)
Definition UnitTopic.h:30
TimestampedUnit()=default
T value
Value.
Definition UnitTopic.h:46