Skip to content

Commit aea0f02

Browse files
committed
Add struct constructors and schema handling to LogValue and NetworkTablesReceiver for nested schemas
1 parent 303858a commit aea0f02

5 files changed

Lines changed: 69 additions & 11 deletions

File tree

.vscode/settings.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,8 @@
66
"**/.settings": true,
77
"**/.factorypath": true
88
},
9-
"C_Cpp.default.configurationProvider": "vscode-wpilib"
9+
"C_Cpp.default.configurationProvider": "vscode-wpilib",
10+
"files.associations": {
11+
"vector": "cpp"
12+
}
1013
}

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ LogValue::LogValue(const std::vector<uint8_t>& data, std::string_view typeString
6464
: m_type(LogType::kStruct), m_value(data), m_typeString(typeString),
6565
m_schema(schema.begin(), schema.end()) {}
6666

67+
// Struct constructor with all schemas (including nested)
68+
LogValue::LogValue(const std::vector<uint8_t>& data, std::string_view typeString,
69+
std::span<const uint8_t> schema,
70+
const std::unordered_map<std::string, std::vector<uint8_t>>& nestedSchemas)
71+
: m_type(LogType::kStruct), m_value(data), m_typeString(typeString),
72+
m_schema(schema.begin(), schema.end()), m_nestedSchemas(nestedSchemas) {}
73+
6774
// Struct array constructor
6875
LogValue::LogValue(const std::vector<uint8_t>& data, std::string_view typeString, bool isArray)
6976
: m_type(isArray ? LogType::kStructArray : LogType::kStruct),
@@ -78,6 +85,17 @@ LogValue::LogValue(const std::vector<uint8_t>& data, std::string_view typeString
7885
m_typeString(typeString),
7986
m_schema(schema.begin(), schema.end()) {}
8087

88+
// Struct array constructor with all schemas (including nested)
89+
LogValue::LogValue(const std::vector<uint8_t>& data, std::string_view typeString,
90+
std::span<const uint8_t> schema,
91+
const std::unordered_map<std::string, std::vector<uint8_t>>& nestedSchemas,
92+
bool isArray)
93+
: m_type(isArray ? LogType::kStructArray : LogType::kStruct),
94+
m_value(data),
95+
m_typeString(typeString),
96+
m_schema(schema.begin(), schema.end()),
97+
m_nestedSchemas(nestedSchemas) {}
98+
8199
std::string LogValue::GetTypeString() const {
82100
// For structs, return the custom type string
83101
if (m_type == LogType::kStruct || m_type == LogType::kStructArray) {

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,12 +176,14 @@ void NetworkTablesReceiver::PublishValue(std::string_view key, const LogValue& v
176176
if (pubIt == m_publishers.end()) {
177177
std::string typeStr = value.GetTypeString(); // e.g., "Pose2d", "SwerveModuleState"
178178

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);
179+
// Publish all struct schemas (including nested ones like Translation2d in Pose2d)
180+
const auto& allSchemas = value.GetAllSchemas();
181+
for (const auto& [schemaName, schemaBytes] : allSchemas) {
182+
// Only publish each schema once
183+
if (m_publishedSchemas.find(schemaName) == m_publishedSchemas.end()) {
184+
m_inst.AddSchema(schemaName, "structschema", schemaBytes);
185+
m_publishedSchemas.insert(schemaName);
186+
}
185187
}
186188

187189
// Create RawTopic publisher with type string

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

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <optional>
66
#include <span>
77
#include <string>
8+
#include <unordered_map>
89
#include <variant>
910
#include <vector>
1011

@@ -81,13 +82,24 @@ class LogValue {
8182
LogValue(const std::vector<uint8_t>& data, std::string_view typeString,
8283
std::span<const uint8_t> schema);
8384

85+
// Constructor for struct data with all schemas (including nested)
86+
LogValue(const std::vector<uint8_t>& data, std::string_view typeString,
87+
std::span<const uint8_t> schema,
88+
const std::unordered_map<std::string, std::vector<uint8_t>>& nestedSchemas);
89+
8490
// Constructor for struct arrays
8591
LogValue(const std::vector<uint8_t>& data, std::string_view typeString, bool isArray);
8692

8793
// Constructor for struct arrays with schema
8894
LogValue(const std::vector<uint8_t>& data, std::string_view typeString,
8995
std::span<const uint8_t> schema, bool isArray);
9096

97+
// Constructor for struct arrays with all schemas (including nested)
98+
LogValue(const std::vector<uint8_t>& data, std::string_view typeString,
99+
std::span<const uint8_t> schema,
100+
const std::unordered_map<std::string, std::vector<uint8_t>>& nestedSchemas,
101+
bool isArray);
102+
91103
// Constructor for raw binary data (no default parameter to avoid ambiguity)
92104
LogValue(const std::vector<uint8_t>& value, bool isStruct);
93105

@@ -162,13 +174,22 @@ class LogValue {
162174
ValueVariant m_value;
163175
std::string m_typeString; // For struct types (e.g., "Pose2d")
164176
std::vector<uint8_t> m_schema; // For struct schema bytes (NT4 schema publishing)
177+
std::unordered_map<std::string, std::vector<uint8_t>> m_nestedSchemas; // Nested struct schemas
165178

166179
public:
167180
/**
168181
* Get the schema bytes for struct types.
169182
* Returns empty span for non-struct types.
170183
*/
171184
std::span<const uint8_t> GetSchema() const { return m_schema; }
185+
186+
/**
187+
* Get all nested schemas (including the main schema).
188+
* Returns map of typeName -> schema bytes.
189+
*/
190+
const std::unordered_map<std::string, std::vector<uint8_t>>& GetAllSchemas() const {
191+
return m_nestedSchemas;
192+
}
172193
};
173194

174195
/**
@@ -190,8 +211,14 @@ LogValue MakeStructValue(const T& structValue) {
190211
// Get schema bytes
191212
auto schemaBytes = wpi::GetStructSchemaBytes<T>();
192213

193-
// Create LogValue with type string and schema
194-
return LogValue(buffer, std::string(descriptor.GetTypeName()), schemaBytes);
214+
// Collect all schemas (including nested structs like Translation2d in Pose2d)
215+
std::unordered_map<std::string, std::vector<uint8_t>> allSchemas;
216+
wpi::ForEachStructSchema<T>([&allSchemas](std::string_view name, std::string_view schema) {
217+
allSchemas[std::string(name)] = std::vector<uint8_t>(schema.begin(), schema.end());
218+
});
219+
220+
// Create LogValue with type string, schema, and all nested schemas
221+
return LogValue(buffer, std::string(descriptor.GetTypeName()), schemaBytes, allSchemas);
195222
}
196223

197224
/**
@@ -212,8 +239,14 @@ LogValue MakeStructArrayValue(std::span<const T> structArray) {
212239
// Get schema bytes
213240
auto schemaBytes = wpi::GetStructSchemaBytes<T>();
214241

215-
// Create LogValue with type string, schema, and array flag
216-
return LogValue(buffer, std::string(descriptor.GetTypeName()), schemaBytes, true);
242+
// Collect all schemas (including nested structs)
243+
std::unordered_map<std::string, std::vector<uint8_t>> allSchemas;
244+
wpi::ForEachStructSchema<T>([&allSchemas](std::string_view name, std::string_view schema) {
245+
allSchemas[std::string(name)] = std::vector<uint8_t>(schema.begin(), schema.end());
246+
});
247+
248+
// Create LogValue with type string, schema, all nested schemas, and array flag
249+
return LogValue(buffer, std::string(descriptor.GetTypeName()), schemaBytes, allSchemas, true);
217250
}
218251

219252
} // namespace telemetrykit

src/main/native/include/telemetrykit/receiver/NetworkTablesReceiver.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <string>
55
#include <string_view>
66
#include <unordered_map>
7+
#include <unordered_set>
78
#include <variant>
89

910
#include <networktables/BooleanArrayTopic.h>
@@ -87,6 +88,7 @@ class NetworkTablesReceiver : public LogDataReceiver {
8788
nt::NetworkTableInstance m_inst;
8889
std::unordered_map<std::string, PublisherVariant> m_publishers;
8990
std::unordered_map<std::string, LogValue> m_lastValues; // For change detection
91+
std::unordered_set<std::string> m_publishedSchemas; // Track published schemas to avoid duplicates
9092
};
9193

9294
} // namespace telemetrykit

0 commit comments

Comments
 (0)