Skip to content

Commit 303858a

Browse files
committed
Add struct constructors and schema handling to LogValue and update NetworkTablesReceiver and WPILogWriter for schema publishing
1 parent 71d96d4 commit 303858a

4 files changed

Lines changed: 64 additions & 10 deletions

File tree

src/main/native/cpp/core/LogValue.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,26 @@ LogValue::LogValue(const std::vector<uint8_t>& value, bool isStruct)
5858
LogValue::LogValue(const std::vector<uint8_t>& data, std::string_view typeString)
5959
: m_type(LogType::kStruct), m_value(data), m_typeString(typeString) {}
6060

61+
// Struct constructor with type string and schema
62+
LogValue::LogValue(const std::vector<uint8_t>& data, std::string_view typeString,
63+
std::span<const uint8_t> schema)
64+
: m_type(LogType::kStruct), m_value(data), m_typeString(typeString),
65+
m_schema(schema.begin(), schema.end()) {}
66+
6167
// Struct array constructor
6268
LogValue::LogValue(const std::vector<uint8_t>& data, std::string_view typeString, bool isArray)
6369
: m_type(isArray ? LogType::kStructArray : LogType::kStruct),
6470
m_value(data),
6571
m_typeString(typeString) {}
6672

73+
// Struct array constructor with schema
74+
LogValue::LogValue(const std::vector<uint8_t>& data, std::string_view typeString,
75+
std::span<const uint8_t> schema, bool isArray)
76+
: m_type(isArray ? LogType::kStructArray : LogType::kStruct),
77+
m_value(data),
78+
m_typeString(typeString),
79+
m_schema(schema.begin(), schema.end()) {}
80+
6781
std::string LogValue::GetTypeString() const {
6882
// For structs, return the custom type string
6983
if (m_type == LogType::kStruct || m_type == LogType::kStructArray) {

src/main/native/cpp/receiver/NetworkTablesReceiver.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,21 @@ void NetworkTablesReceiver::PublishValue(std::string_view key, const LogValue& v
171171

172172
case LogType::kStruct:
173173
case LogType::kStructArray: {
174-
// For structs, publish as raw with type string metadata
174+
// For structs, publish as RawTopic with type string metadata.
175+
// NT4 clients like AdvantageScope will use the type string and schema to deserialize.
175176
if (pubIt == m_publishers.end()) {
177+
std::string typeStr = value.GetTypeString(); // e.g., "Pose2d", "SwerveModuleState"
178+
179+
// Publish struct schema to NetworkTables if we have it
180+
auto schema = value.GetSchema();
181+
if (!schema.empty()) {
182+
// Use "struct:TypeName" format for schema registration
183+
std::string fullTypeStr = "struct:" + typeStr;
184+
m_inst.AddSchema(typeStr, fullTypeStr, schema);
185+
}
186+
187+
// Create RawTopic publisher with type string
176188
auto topic = m_inst.GetRawTopic(keyStr);
177-
std::string typeStr = value.GetTypeString();
178189
m_publishers[keyStr] = topic.Publish(typeStr);
179190
pubIt = m_publishers.find(keyStr);
180191
}

src/main/native/cpp/receiver/WPILogWriter.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,15 @@ int WPILogWriter::GetOrCreateEntry(std::string_view key, const LogValue& value)
112112
case LogType::kRaw:
113113
entryId = m_log->Start(keyStr, "raw");
114114
break;
115-
case LogType::kStruct:
115+
case LogType::kStruct: {
116+
// For structs, use "struct:TypeName" format (e.g., "struct:Pose2d")
117+
std::string typeStr = "struct:" + value.GetTypeString();
118+
entryId = m_log->Start(keyStr, typeStr);
119+
break;
120+
}
116121
case LogType::kStructArray: {
117-
// For structs, use the type string
118-
std::string typeStr = value.GetTypeString();
122+
// For struct arrays, use "struct:TypeName[]" format (e.g., "struct:Pose2d[]")
123+
std::string typeStr = "struct:" + value.GetTypeString() + "[]";
119124
entryId = m_log->Start(keyStr, typeStr);
120125
break;
121126
}

src/main/native/include/telemetrykit/core/LogValue.h

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include <variant>
99
#include <vector>
1010

11+
#include <wpi/struct/Struct.h>
12+
1113
namespace telemetrykit {
1214

1315
/**
@@ -75,9 +77,17 @@ class LogValue {
7577
// Constructor for struct data with type string (MUST come before bool constructor)
7678
LogValue(const std::vector<uint8_t>& data, std::string_view typeString);
7779

80+
// Constructor for struct data with type string and schema
81+
LogValue(const std::vector<uint8_t>& data, std::string_view typeString,
82+
std::span<const uint8_t> schema);
83+
7884
// Constructor for struct arrays
7985
LogValue(const std::vector<uint8_t>& data, std::string_view typeString, bool isArray);
8086

87+
// Constructor for struct arrays with schema
88+
LogValue(const std::vector<uint8_t>& data, std::string_view typeString,
89+
std::span<const uint8_t> schema, bool isArray);
90+
8191
// Constructor for raw binary data (no default parameter to avoid ambiguity)
8292
LogValue(const std::vector<uint8_t>& value, bool isStruct);
8393

@@ -151,14 +161,22 @@ class LogValue {
151161
LogType m_type;
152162
ValueVariant m_value;
153163
std::string m_typeString; // For struct types (e.g., "Pose2d")
164+
std::vector<uint8_t> m_schema; // For struct schema bytes (NT4 schema publishing)
165+
166+
public:
167+
/**
168+
* Get the schema bytes for struct types.
169+
* Returns empty span for non-struct types.
170+
*/
171+
std::span<const uint8_t> GetSchema() const { return m_schema; }
154172
};
155173

156174
/**
157175
* Helper function to create a LogValue from a WPILib struct.
158176
*
159177
* Example:
160178
* frc::Pose2d pose{...};
161-
* LogValue value = LogValue::FromStruct(pose);
179+
* LogValue value = MakeStructValue(pose);
162180
*/
163181
template<typename T>
164182
LogValue MakeStructValue(const T& structValue) {
@@ -169,8 +187,11 @@ LogValue MakeStructValue(const T& structValue) {
169187
std::vector<uint8_t> buffer(descriptor.GetSize());
170188
descriptor.Pack(buffer, structValue);
171189

172-
// Create LogValue with type string
173-
return LogValue(buffer, std::string(descriptor.GetTypeName()));
190+
// Get schema bytes
191+
auto schemaBytes = wpi::GetStructSchemaBytes<T>();
192+
193+
// Create LogValue with type string and schema
194+
return LogValue(buffer, std::string(descriptor.GetTypeName()), schemaBytes);
174195
}
175196

176197
/**
@@ -188,8 +209,11 @@ LogValue MakeStructArrayValue(std::span<const T> structArray) {
188209
descriptor.Pack(slice, structArray[i]);
189210
}
190211

191-
// Create LogValue with type string and array flag
192-
return LogValue(buffer, std::string(descriptor.GetTypeName()), true);
212+
// Get schema bytes
213+
auto schemaBytes = wpi::GetStructSchemaBytes<T>();
214+
215+
// Create LogValue with type string, schema, and array flag
216+
return LogValue(buffer, std::string(descriptor.GetTypeName()), schemaBytes, true);
193217
}
194218

195219
} // namespace telemetrykit

0 commit comments

Comments
 (0)