From 6c0d254852dec65f20122ba9d9354d4f86aaf79e Mon Sep 17 00:00:00 2001 From: Will Sobel Date: Sun, 12 May 2024 18:32:38 -0400 Subject: [PATCH 1/3] fixed pretty printing for assets, added asset header to mqtt, and fixed initial smaple publish when machine is idle. --- conanfile.py | 2 +- src/mtconnect/agent.cpp | 4 ++-- .../device_model/data_item/data_item.cpp | 2 +- .../device_model/data_item/data_item.hpp | 4 ++-- src/mtconnect/mqtt/mqtt_client_impl.hpp | 8 +++---- .../sink/mqtt_sink/mqtt2_service.cpp | 22 ++++++++++--------- .../sink/mqtt_sink/mqtt2_service.hpp | 2 +- src/mtconnect/sink/rest_sink/rest_service.cpp | 11 ++++++---- test_package/agent_test.cpp | 3 +-- 9 files changed, 31 insertions(+), 27 deletions(-) diff --git a/conanfile.py b/conanfile.py index 5dfe85877..9131be39e 100644 --- a/conanfile.py +++ b/conanfile.py @@ -9,7 +9,7 @@ class MTConnectAgentConan(ConanFile): name = "mtconnect_agent" - version = "2.2" + version = "2.3" url = "https://github.com/mtconnect/cppagent.git" license = "Apache License 2.0" settings = "os", "compiler", "arch", "build_type" diff --git a/src/mtconnect/agent.cpp b/src/mtconnect/agent.cpp index d8f69601f..660c6f18b 100644 --- a/src/mtconnect/agent.cpp +++ b/src/mtconnect/agent.cpp @@ -289,7 +289,7 @@ namespace mtconnect { { if (item.expired()) continue; - + auto di = item.lock(); if (di->hasInitialValue()) { @@ -297,7 +297,7 @@ namespace mtconnect { } } } - + std::lock_guard lock(m_circularBuffer); if (m_circularBuffer.addToBuffer(observation) != 0) { diff --git a/src/mtconnect/device_model/data_item/data_item.cpp b/src/mtconnect/device_model/data_item/data_item.cpp index 162c31d7c..0a21d976c 100644 --- a/src/mtconnect/device_model/data_item/data_item.cpp +++ b/src/mtconnect/device_model/data_item/data_item.cpp @@ -201,7 +201,7 @@ namespace mtconnect { } } } - + if (const auto &init = maybeGet("InitialValue"); init) { m_initialValue = *init; diff --git a/src/mtconnect/device_model/data_item/data_item.hpp b/src/mtconnect/device_model/data_item/data_item.hpp index 562f98f1b..3efcad2f9 100644 --- a/src/mtconnect/device_model/data_item/data_item.hpp +++ b/src/mtconnect/device_model/data_item/data_item.hpp @@ -139,11 +139,11 @@ namespace mtconnect { /// @brief get the topic name leaf node for this data item /// @return the topic name const auto &getTopicName() const { return m_topicName; } - + /// @brief get the initial value if one is set /// @return optional initial value const auto &getInitialValue() const { return m_initialValue; } - + Category getCategory() const { return m_category; } Representation getRepresentation() const { return m_representation; } SpecialClass getSpecialClass() const { return m_specialClass; } diff --git a/src/mtconnect/mqtt/mqtt_client_impl.hpp b/src/mtconnect/mqtt/mqtt_client_impl.hpp index 25b039b6a..38ae0f5ea 100644 --- a/src/mtconnect/mqtt/mqtt_client_impl.hpp +++ b/src/mtconnect/mqtt/mqtt_client_impl.hpp @@ -164,7 +164,7 @@ namespace mtconnect { m_connected = false; if (m_handler && m_handler->m_disconnected) m_handler->m_disconnected(shared_from_this()); - m_handler->m_disconnected(shared_from_this()); + m_handler->m_disconnected(shared_from_this()); if (m_running) { reconnect(); @@ -419,7 +419,7 @@ namespace mtconnect { { return static_pointer_cast(shared_from_this()); } - + /// @brief Get the Mqtt TCP Client /// @return pointer to the Mqtt TCP Client auto &getClient() @@ -501,7 +501,7 @@ namespace mtconnect { { return static_pointer_cast(shared_from_this()); } - + /// @brief Get the Mqtt TLS WebSocket Client /// @return pointer to the Mqtt TLS WebSocket Client auto &getClient() @@ -540,7 +540,7 @@ namespace mtconnect { { return static_pointer_cast(shared_from_this()); } - + /// @brief Get the Mqtt TLS WebSocket Client /// @return pointer to the Mqtt TLS WebSocket Client auto &getClient() diff --git a/src/mtconnect/sink/mqtt_sink/mqtt2_service.cpp b/src/mtconnect/sink/mqtt_sink/mqtt2_service.cpp index 0a859fa84..40fe0347a 100644 --- a/src/mtconnect/sink/mqtt_sink/mqtt2_service.cpp +++ b/src/mtconnect/sink/mqtt_sink/mqtt2_service.cpp @@ -185,7 +185,7 @@ namespace mtconnect { } } - auto seq = m_sinkContract->getCircularBuffer().getSequence(); + auto seq = publishCurrent(boost::system::error_code {}); for (auto &dev : m_sinkContract->getDevices()) { FilterSet filterSet = filterForDevice(dev); @@ -197,10 +197,8 @@ namespace mtconnect { sampler->observe(seq, [this](const std::string &id) { return m_sinkContract->getDataItemById(id).get(); }); - sampler->handlerCompleted(); + publishSample(sampler); } - - publishCurrent(boost::system::error_code {}); } /// @brief publish sample when observations arrive. @@ -244,18 +242,20 @@ namespace mtconnect { return end; } - void Mqtt2Service::publishCurrent(boost::system::error_code ec) + SequenceNumber_t Mqtt2Service::publishCurrent(boost::system::error_code ec) { + SequenceNumber_t firstSeq, seq = 0; + if (ec) { LOG(warning) << "Mqtt2Service::publishCurrent: " << ec.message(); - return; + return 0; } if (!m_client->isRunning() || !m_client->isConnected()) { LOG(warning) << "Mqtt2Service::publishCurrent: client stopped"; - return; + return 0; } for (auto &device : m_sinkContract->getDevices()) @@ -264,7 +264,6 @@ namespace mtconnect { LOG(debug) << "Publishing current for: " << topic; ObservationList observations; - SequenceNumber_t firstSeq, seq; auto filterSet = filterForDevice(device); { @@ -288,6 +287,8 @@ namespace mtconnect { m_currentTimer.expires_after(m_currentInterval); m_currentTimer.async_wait(boost::asio::bind_executor( m_strand, boost::bind(&Mqtt2Service::publishCurrent, this, _1))); + + return seq; } bool Mqtt2Service::publish(observation::ObservationPtr &observation) @@ -325,8 +326,9 @@ namespace mtconnect { LOG(debug) << "Publishing Asset to topic: " << topic; - auto doc = m_jsonPrinter->print(asset); - + asset::AssetList list {asset}; + auto doc = m_printer->printAssets( + m_instanceId, uint32_t(m_sinkContract->getAssetStorage()->getMaxAssets()), 1, list); stringstream buffer; buffer << doc; diff --git a/src/mtconnect/sink/mqtt_sink/mqtt2_service.hpp b/src/mtconnect/sink/mqtt_sink/mqtt2_service.hpp index 0e1ddbab4..981d58adc 100644 --- a/src/mtconnect/sink/mqtt_sink/mqtt2_service.hpp +++ b/src/mtconnect/sink/mqtt_sink/mqtt2_service.hpp @@ -96,7 +96,7 @@ namespace mtconnect { void pubishInitialContent(); /// @brief Publish a current using `CurrentInterval` option. - void publishCurrent(boost::system::error_code ec); + SequenceNumber_t publishCurrent(boost::system::error_code ec); /// @brief publish sample when observations arrive. SequenceNumber_t publishSample(std::shared_ptr sampler); diff --git a/src/mtconnect/sink/rest_sink/rest_service.cpp b/src/mtconnect/sink/rest_sink/rest_service.cpp index 6e123ed84..90e8c49ac 100644 --- a/src/mtconnect/sink/rest_sink/rest_service.cpp +++ b/src/mtconnect/sink/rest_sink/rest_service.cpp @@ -523,29 +523,32 @@ namespace mtconnect { auto removed = *request->parameter("removed"); auto count = *request->parameter("count"); auto printer = printerForAccepts(request->m_accepts); + auto pretty = *request->parameter("pretty"); respond(session, assetRequest(printer, count, removed, request->parameter("type"), - request->parameter("device"))); + request->parameter("device"), pretty)); return true; }; auto idHandler = [&](SessionPtr session, RequestPtr request) -> bool { auto asset = request->parameter("assetIds"); + auto pretty = *request->parameter("pretty"); if (asset) { auto printer = m_sinkContract->getPrinter(acceptFormat(request->m_accepts)); - + list ids; stringstream str(*asset); string id; while (getline(str, id, ';')) ids.emplace_back(id); - respond(session, assetIdsRequest(printer, ids)); + respond(session, assetIdsRequest(printer, ids, pretty)); } else { auto printer = printerForAccepts(request->m_accepts); - auto error = printError(printer, "INVALID_REQUEST", "No asset given"); + auto pretty = *request->parameter("pretty"); + auto error = printError(printer, "INVALID_REQUEST", "No asset given", pretty); respond(session, make_unique(rest_sink::status::bad_request, error, printer->mimeType())); } diff --git a/test_package/agent_test.cpp b/test_package/agent_test.cpp index 798e8a9c6..f14664cc3 100644 --- a/test_package/agent_test.cpp +++ b/test_package/agent_test.cpp @@ -3089,12 +3089,11 @@ TEST_F(AgentTest, should_initialize_observaton_to_initial_value_when_available) PARSE_XML_RESPONSE("/current"); ASSERT_XML_PATH_EQUAL(doc, "//m:DeviceStream//m:PartCount", "UNAVAILABLE"); } - + m_agentTestHelper->m_adapter->processData("2024-01-22T20:00:00Z|avail|AVAILABLE"); { PARSE_XML_RESPONSE("/current"); ASSERT_XML_PATH_EQUAL(doc, "//m:DeviceStream//m:PartCount", "0"); } - } From b5e700e962a24bd77c35fe5858d93753e6410657 Mon Sep 17 00:00:00 2001 From: Will Sobel Date: Sun, 12 May 2024 19:29:53 -0400 Subject: [PATCH 2/3] fixed failing test --- test_package/mqtt_sink_2_test.cpp | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/test_package/mqtt_sink_2_test.cpp b/test_package/mqtt_sink_2_test.cpp index 111748a74..1a5f56b6e 100644 --- a/test_package/mqtt_sink_2_test.cpp +++ b/test_package/mqtt_sink_2_test.cpp @@ -248,15 +248,23 @@ TEST_F(MqttSink2Test, mqtt_sink_should_publish_Sample) auto handler = make_unique(); bool gotSample = false; - handler->m_receive = [&gotSample](std::shared_ptr client, const std::string &topic, + bool first = true; + handler->m_receive = [&gotSample, &first](std::shared_ptr client, const std::string &topic, const std::string &payload) { - EXPECT_EQ("MTConnect/Sample/000", topic); - - auto jdoc = json::parse(payload); - auto streams = jdoc.at("/MTConnectStreams/Streams/0/DeviceStream"_json_pointer); - EXPECT_EQ(string("LinuxCNC"), streams.at("/name"_json_pointer).get()); - - gotSample = true; + if (first) + { + first = false; + } + else + { + EXPECT_EQ("MTConnect/Sample/000", topic); + + auto jdoc = json::parse(payload); + auto streams = jdoc.at("/MTConnectStreams/Streams/0/DeviceStream"_json_pointer); + EXPECT_EQ(string("LinuxCNC"), streams.at("/name"_json_pointer).get()); + + gotSample = true; + } }; createClient(options, std::move(handler)); @@ -267,9 +275,9 @@ TEST_F(MqttSink2Test, mqtt_sink_should_publish_Sample) auto service = m_agentTestHelper->getMqtt2Service(); - ASSERT_TRUE(waitFor(60s, [&service]() { return service->isConnected(); })); - ASSERT_FALSE(gotSample); - + ASSERT_TRUE(waitFor(60s, [&first]() { return !first; })); + ASSERT_FALSE(first); + m_agentTestHelper->m_adapter->processData("2021-02-01T12:00:00Z|line|204"); ASSERT_TRUE(waitFor(10s, [&gotSample]() { return gotSample; })); } From 15564b48406d5991e4ac662c45c29ef3035d133a Mon Sep 17 00:00:00 2001 From: William Sobel Date: Mon, 13 May 2024 04:43:54 -0400 Subject: [PATCH 3/3] Update CMakeLists.txt Verizon 2.3.0.9 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 95ce6c8aa..0ab7d6938 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ set(AGENT_VERSION_MAJOR 2) set(AGENT_VERSION_MINOR 3) set(AGENT_VERSION_PATCH 0) -set(AGENT_VERSION_BUILD 8) +set(AGENT_VERSION_BUILD 9) set(AGENT_VERSION_RC "") # This minimum version is to support Visual Studio 2019 and C++ feature checking and FetchContent