diff --git a/apps/ied_simulator/src/MmsClientController.cpp b/apps/ied_simulator/src/MmsClientController.cpp index d0d74308b..7b5c68006 100644 --- a/apps/ied_simulator/src/MmsClientController.cpp +++ b/apps/ied_simulator/src/MmsClientController.cpp @@ -454,7 +454,8 @@ bool MmsClientController::connectToIed() { worker->session = std::move(session); if (self) { - QMetaObject::invokeMethod(self, [self, generation, model, associationProfile] { + const auto wireSummary = QString::fromStdString(discovery->summary()); + QMetaObject::invokeMethod(self, [self, generation, model, associationProfile, wireSummary] { if (!self || self->generation_ != generation) return; self->treeModel_.applyDocument(*model); self->iedName_ = QString::fromStdString(model->identity.ied_name); @@ -475,6 +476,9 @@ bool MmsClientController::connectToIed() { .arg(self->logicalDeviceCount_) .arg(self->logicalNodeCount_) .arg(self->dataAttributeCount_)); + // Capture the immutable worker result once; never query + // session counters from the GUI or issue a diagnostic Read. + self->appendDiagnostic(wireSummary); emit self->modelChanged(); emit self->stateChanged(); }, Qt::QueuedConnection); diff --git a/src/mms/live_discovery.cpp b/src/mms/live_discovery.cpp index e39bed3cc..d89e09a33 100644 --- a/src/mms/live_discovery.cpp +++ b/src/mms/live_discovery.cpp @@ -262,6 +262,11 @@ std::string MmsLiveDiscoveryResult::summary() const { << data_set_directories.size() << ", rcbReads=" << successful_controls << '/' << report_controls.size() + << ", wireRequests=" << wire_budget.total() + << " [NameList=" << wire_budget.get_name_list + << ", GVA=" << wire_budget.get_variable_access_attributes + << ", DataSetDirectory=" << wire_budget.get_named_variable_list_attributes + << ", RCBRead=" << wire_budget.read_report_controls << ']' << ", diagnostics=" << diagnostics.size() << '.'; return stream.str(); } diff --git a/tests/test_live_discovery.cpp b/tests/test_live_discovery.cpp index 82b03b87f..9a7fc8068 100644 --- a/tests/test_live_discovery.cpp +++ b/tests/test_live_discovery.cpp @@ -485,6 +485,8 @@ void live_discovery_builds_csharp_compatible_read_only_model() { CHECK(result.wire_budget.get_named_variable_list_attributes == 1U); CHECK(result.wire_budget.read_report_controls == 1U); CHECK(result.wire_budget.total() == read_only_requests); + const auto budgetSummary = result.summary(); + CHECK(budgetSummary.find("wireRequests=6 [NameList=3, GVA=1, DataSetDirectory=1, RCBRead=1]") != std::string::npos); } @@ -638,6 +640,7 @@ void verified_data_set_hints_restore_late_ln_type_schema() { CHECK(result.wire_budget.get_variable_access_attributes == 2U); CHECK(result.wire_budget.read_report_controls == 0U); CHECK(result.wire_budget.total() == 6U); + CHECK(result.summary().find("wireRequests=6 [NameList=3, GVA=2, DataSetDirectory=1, RCBRead=0]") != std::string::npos); } void disconnected_optional_probes_do_not_inflate_wire_budget() {