[ntcore] NetworkTables 4 (#3217)

This commit is contained in:
Peter Johnson
2022-10-08 10:01:31 -07:00
committed by GitHub
parent 90cfa00115
commit 77301b126c
380 changed files with 34573 additions and 22095 deletions

View File

@@ -17,16 +17,19 @@
using namespace glass;
NetworkTablesProvider::NetworkTablesProvider(Storage& storage)
: NetworkTablesProvider{storage, nt::GetDefaultInstance()} {}
: NetworkTablesProvider{storage, nt::NetworkTableInstance::GetDefault()} {}
NetworkTablesProvider::NetworkTablesProvider(Storage& storage, NT_Inst inst)
NetworkTablesProvider::NetworkTablesProvider(Storage& storage,
nt::NetworkTableInstance inst)
: Provider{storage.GetChild("windows")},
m_nt{inst},
m_inst{inst},
m_topicPoller{inst},
m_valuePoller{inst},
m_typeCache{storage.GetChild("types")} {
storage.SetCustomApply([this] {
m_listener =
m_nt.AddListener("", NT_NOTIFY_LOCAL | NT_NOTIFY_NEW |
NT_NOTIFY_DELETE | NT_NOTIFY_IMMEDIATE);
m_topicListener = m_topicPoller.Add({{""}}, NT_TOPIC_NOTIFY_PUBLISH |
NT_TOPIC_NOTIFY_UNPUBLISH |
NT_TOPIC_NOTIFY_IMMEDIATE);
for (auto&& childIt : m_storage.GetChildren()) {
auto id = childIt.key();
auto typePtr = m_typeCache.FindValue(id);
@@ -41,16 +44,15 @@ NetworkTablesProvider::NetworkTablesProvider(Storage& storage, NT_Inst inst)
}
auto entry = GetOrCreateView(
builderIt->second,
nt::GetEntry(m_nt.GetInstance(), fmt::format("{}/.type", id)), id);
builderIt->second, m_inst.GetTopic(fmt::format("{}/.type", id)), id);
if (entry) {
Show(entry, nullptr);
}
}
});
storage.SetCustomClear([this, &storage] {
nt::RemoveEntryListener(m_listener);
m_listener = 0;
m_topicPoller.Remove(m_topicListener);
m_topicListener = 0;
for (auto&& modelEntry : m_modelEntries) {
modelEntry->model.reset();
}
@@ -101,35 +103,57 @@ void NetworkTablesProvider::Update() {
Provider::Update();
// add/remove entries from NT changes
for (auto&& event : m_nt.PollListener()) {
for (auto&& event : m_topicPoller.ReadQueue()) {
// look for .type fields
std::string_view eventName{event.name};
if (!wpi::ends_with(eventName, "/.type") || !event.value ||
!event.value->IsString()) {
if (!wpi::ends_with(event.info.name, "/.type") ||
event.info.type != NT_STRING || event.info.type_str != "string") {
continue;
}
if (event.flags & NT_TOPIC_NOTIFY_UNPUBLISH) {
auto it = m_topicMap.find(event.info.topic);
if (it != m_topicMap.end()) {
m_valuePoller.Remove(it->second.listener);
m_topicMap.erase(it);
}
auto it2 = std::find_if(
m_viewEntries.begin(), m_viewEntries.end(), [&](const auto& elem) {
return static_cast<Entry*>(elem->modelEntry)
->typeTopic.GetHandle() == event.info.topic;
});
if (it2 != m_viewEntries.end()) {
m_viewEntries.erase(it2);
}
} else if (event.flags & NT_TOPIC_NOTIFY_PUBLISH) {
// subscribe to it
SubListener sublistener;
sublistener.subscriber = nt::StringTopic{event.info.topic}.Subscribe("");
sublistener.listener =
m_valuePoller.Add(sublistener.subscriber,
NT_VALUE_NOTIFY_LOCAL | NT_VALUE_NOTIFY_IMMEDIATE);
m_topicMap.try_emplace(event.info.topic, std::move(sublistener));
}
}
// handle actual .type strings
for (auto&& event : m_valuePoller.ReadQueue()) {
if (!event.value.IsString()) {
continue;
}
auto tableName = wpi::drop_back(eventName, 6);
// only handle ones where we have a builder
auto builderIt = m_typeMap.find(event.value->GetString());
auto builderIt = m_typeMap.find(event.value.GetString());
if (builderIt == m_typeMap.end()) {
continue;
}
if (event.flags & NT_NOTIFY_DELETE) {
auto it = std::find_if(
m_viewEntries.begin(), m_viewEntries.end(), [&](const auto& elem) {
return static_cast<Entry*>(elem->modelEntry)->typeEntry ==
event.entry;
});
if (it != m_viewEntries.end()) {
m_viewEntries.erase(it);
}
} else if (event.flags & NT_NOTIFY_NEW) {
GetOrCreateView(builderIt->second, event.entry, tableName);
// cache the type
m_typeCache.SetString(tableName, event.value->GetString());
}
auto topicName = nt::GetTopicName(event.topic);
auto tableName = wpi::drop_back(topicName, 6);
GetOrCreateView(builderIt->second, nt::Topic{event.topic}, tableName);
// cache the type
m_typeCache.SetString(tableName, event.value.GetString());
}
}
@@ -149,7 +173,7 @@ void NetworkTablesProvider::Show(ViewEntry* entry, Window* window) {
// get or create model
if (!entry->modelEntry->model) {
entry->modelEntry->model =
entry->modelEntry->createModel(m_nt.GetInstance(), entry->name.c_str());
entry->modelEntry->createModel(m_inst, entry->name.c_str());
}
if (!entry->modelEntry->model) {
return;
@@ -180,22 +204,22 @@ void NetworkTablesProvider::Show(ViewEntry* entry, Window* window) {
}
NetworkTablesProvider::ViewEntry* NetworkTablesProvider::GetOrCreateView(
const Builder& builder, NT_Entry typeEntry, std::string_view name) {
const Builder& builder, nt::Topic typeTopic, std::string_view name) {
// get view entry if it already exists
auto viewIt = FindViewEntry(name);
if (viewIt != m_viewEntries.end() && (*viewIt)->name == name) {
// make sure typeEntry is set in model
static_cast<Entry*>((*viewIt)->modelEntry)->typeEntry = typeEntry;
static_cast<Entry*>((*viewIt)->modelEntry)->typeTopic = typeTopic;
return viewIt->get();
}
// get or create model entry
auto modelIt = FindModelEntry(name);
if (modelIt != m_modelEntries.end() && (*modelIt)->name == name) {
static_cast<Entry*>(modelIt->get())->typeEntry = typeEntry;
static_cast<Entry*>(modelIt->get())->typeTopic = typeTopic;
} else {
modelIt = m_modelEntries.emplace(
modelIt, std::make_unique<Entry>(typeEntry, name, builder));
modelIt, std::make_unique<Entry>(typeTopic, name, builder));
}
// create new view entry