From 2cb49ca574162d5bddfa68d3c73d53e070aedc65 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 16 Nov 2023 19:15:47 +0000 Subject: [PATCH 01/48] init --- ext/build.sh | 12 +- scripts/install_dependencies.sh | 3 + .../TelematicBridgePlugin/CMakeLists.txt | 19 ++ .../TelematicBridgePlugin/manifest.json | 16 ++ .../src/TelematicBridgeException.h | 18 ++ .../src/TelematicBridgeJ2735MsgWorker.cpp | 126 ++++++++ .../src/TelematicBridgeJ2735MsgWorker.h | 48 ++++ .../src/TelematicBridgePlugin.cpp | 40 +++ .../src/TelematicBridgePlugin.h | 27 ++ .../TelematicBridgePlugin/src/xml2json.h | 272 ++++++++++++++++++ .../TelematicBridgePlugin/test/main.cpp | 7 + .../test/test_TelematicJ2735MsgWorker.cpp | 40 +++ 12 files changed, 627 insertions(+), 1 deletion(-) create mode 100644 src/v2i-hub/TelematicBridgePlugin/CMakeLists.txt create mode 100644 src/v2i-hub/TelematicBridgePlugin/manifest.json create mode 100644 src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeException.h create mode 100644 src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.cpp create mode 100644 src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.h create mode 100644 src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp create mode 100644 src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h create mode 100644 src/v2i-hub/TelematicBridgePlugin/src/xml2json.h create mode 100644 src/v2i-hub/TelematicBridgePlugin/test/main.cpp create mode 100644 src/v2i-hub/TelematicBridgePlugin/test/test_TelematicJ2735MsgWorker.cpp diff --git a/ext/build.sh b/ext/build.sh index 03d2ec4fb..9347dceda 100755 --- a/ext/build.sh +++ b/ext/build.sh @@ -55,4 +55,14 @@ cd NemaTode cmake . make -j${numCPU} make install -popd \ No newline at end of file +popd + +# Nats C API +pushd /tmp +git clone https://github.com/nats-io/nats.c +cd nats.c +cmake . -DNATS_BUILD_NO_SPIN=ON +make -j${numCPU} +make install +popd + diff --git a/scripts/install_dependencies.sh b/scripts/install_dependencies.sh index 2fa104c86..c4ce8727e 100755 --- a/scripts/install_dependencies.sh +++ b/scripts/install_dependencies.sh @@ -31,6 +31,9 @@ DEPENDENCIES="build-essential \ wget \ zip \ zlib1g \ + rapidjson-dev \ + librapidxml-dev \ + libprotobuf-c-dev \ curl" # STOL library dependencies diff --git a/src/v2i-hub/TelematicBridgePlugin/CMakeLists.txt b/src/v2i-hub/TelematicBridgePlugin/CMakeLists.txt new file mode 100644 index 000000000..48305985d --- /dev/null +++ b/src/v2i-hub/TelematicBridgePlugin/CMakeLists.txt @@ -0,0 +1,19 @@ +PROJECT (TelematicBridgePlugin VERSION 7.5.1 LANGUAGES CXX) + +set (TMX_PLUGIN_NAME "Telematic Bridge") + +find_package(RapidJSON REQUIRED) + +BuildTmxPlugin() +TARGET_LINK_LIBRARIES ( ${PROJECT_NAME} tmxutils) + +#################################################### +################## Testing ####################### +#################################################### +enable_testing() +include_directories(${PROJECT_SOURCE_DIR}/src) +add_library(${PROJECT_NAME}_lib src/TelematicBridgeJ2735MsgWorker.cpp) +target_link_libraries(${PROJECT_NAME}_lib PUBLIC tmxutils) +file(GLOB_RECURSE TEST_SOURCES LIST_DIRECTORIES false test/*.h test/*.cpp) +add_executable(${PROJECT_NAME}_test ${TEST_SOURCES}) +target_link_libraries(${PROJECT_NAME}_test PRIVATE ${PROJECT_NAME}_lib gtest) \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/manifest.json b/src/v2i-hub/TelematicBridgePlugin/manifest.json new file mode 100644 index 000000000..530dbe0eb --- /dev/null +++ b/src/v2i-hub/TelematicBridgePlugin/manifest.json @@ -0,0 +1,16 @@ +{ + "name": "TelematicBridge", + "description": "Plugin that listens for TMX messages and forward them to the Telematic cloud services.", + "version": "@PROJECT_VERSION@", + "exeLocation": "/bin/TelematicBridgePlugin", + "coreIpAddr": "127.0.0.1", + "corePort": 24601, + "messageTypes": [], + "configuration": [ + { + "key": "LogLevel", + "default": "INFO", + "description": "The log level for this plugin" + } + ] +} \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeException.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeException.h new file mode 100644 index 000000000..a4893bbdf --- /dev/null +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeException.h @@ -0,0 +1,18 @@ +#pragma once +#include + +namespace TelematicBridge +{ + class TelematicBridgeException : public tmx::TmxException + { + public: + explicit TelematicBridgeException(const std::string &what_arg) : TmxException(what_arg) + { + } + + explicit TelematicBridgeException(const char *what_arg = "") : TmxException(what_arg) + { + } + ~TelematicBridgeException() = default; + }; +} \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.cpp new file mode 100644 index 000000000..5c906ea24 --- /dev/null +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.cpp @@ -0,0 +1,126 @@ +#include "TelematicBridgeJ2735MsgWorker.h" + +namespace TelematicBridge +{ + bool TelematicBridgeJ2735MsgWorker::HexToBytes(const string &hexPaylod, vector &byteBuffer) + { + uint8_t d = 0; + int i = 0; + + for (const char &c : hexPaylod) + { + if (c <= '9' && c >= '0') + { + d = c - '0'; + } + else if (c <= 'F' && c >= 'A') + { + d = c - 55; // c - 'A' + 10 + } + else if (c <= 'f' && c >= 'a') + { + d = c - 87; // c - 'a' + 10; + } + else + { + return false; + } + + if (i % 2) + { + // low order nibble. + byteBuffer.back() |= d; + } + else + { + // high order nibble. + byteBuffer.push_back(d << 4); + } + ++i; + } + return true; + } + + void TelematicBridgeJ2735MsgWorker::DecodeJ2735Msg(const string &hexPaylod, MessageFrame_t* messageFrame) + { + /** + * Decode J2735 message + */ + ostringstream erroross; + vector byte_buffer; + static constexpr size_t max_errbuf_size = 128; + size_t errlen = max_errbuf_size; + if (!HexToBytes(hexPaylod, byte_buffer)) + { + throw TelematicBridgeException("Failed attempt to decode MessageFrame hex string: cannot convert to bytes."); + } + asn_dec_rval_t decode_rval = asn_decode( + 0, + ATS_UNALIGNED_BASIC_PER, + &asn_DEF_MessageFrame, + (void **)&messageFrame, + byte_buffer.data(), + byte_buffer.size()); + + if (decode_rval.code != RC_OK) + { + erroross.str(""); + erroross << "failed ASN.1 binary decoding of element " << asn_DEF_MessageFrame.name << ": "; + if (decode_rval.code == RC_FAIL) + { + erroross << "bad data."; + } + else + { + erroross << "more data expected."; + } + erroross << " Successfully decoded " << decode_rval.consumed << " bytes."; + throw TelematicBridgeException(erroross.str()); + } + } + + string TelematicBridgeJ2735MsgWorker::ConvertJ2735FrameToXML(const MessageFrame_t *messageFrame) + { + /** + * Convert J2735 message into XML + */ + buffer_structure_t xml_buffer = {0, 0, 0}; + asn_enc_rval_t encode_rval = xer_encode( + &asn_DEF_MessageFrame, + messageFrame, + XER_F_CANONICAL, + dynamic_buffer_append, + static_cast(&xml_buffer)); + if (encode_rval.encoded == -1) + { + throw TelematicBridgeException("Failed to convert message with ID (=" + to_string(messageFrame->messageId) + ") to XML "); + } + return string(xml_buffer.buffer); + } + + int TelematicBridgeJ2735MsgWorker::dynamic_buffer_append(const void *buffer, size_t size, void *app_key) + { + buffer_structure_t *xb = static_cast(app_key); + + while (xb->buffer_size + size + 1 > xb->allocated_size) + { + // increase size of buffer. + size_t new_size = 2 * (xb->allocated_size ? xb->allocated_size : 64); + char *new_buf = static_cast(MALLOC(new_size)); + if (!new_buf) + return -1; + // move old to new. + memcpy(new_buf, xb->buffer, xb->buffer_size); + + FREEMEM(xb->buffer); + xb->buffer = new_buf; + xb->allocated_size = new_size; + } + + memcpy(xb->buffer + xb->buffer_size, buffer, size); + xb->buffer_size += size; + // null terminate the string. + xb->buffer[xb->buffer_size] = '\0'; + return 0; + } +} // TelematicBridge \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.h new file mode 100644 index 000000000..34787a9e9 --- /dev/null +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.h @@ -0,0 +1,48 @@ +#pragma once +#include "PluginLog.h" +#include +#include "TelematicBridgeException.h" + +using namespace tmx::utils; +using namespace std; +using namespace tmx::messages; + +namespace TelematicBridge +{ + typedef struct buffer_structure + { + char *buffer; //buffer array + size_t buffer_size; // this is really where we will write next. + size_t allocated_size; // this is the total size of the buffer. + } buffer_structure_t; + + class TelematicBridgeJ2735MsgWorker + { + public: + /** + * @brief Convert hex string into a vector of bytes + * @param string input hex string payload + * @param vector byte buffer to be updated. + * @return bool indicator whether conversion is successful. + */ + static bool HexToBytes(const string &hexPaylod, vector &byteBuffer); + + /** + * @brief Decode J2735 message and populate the J2735 data frame + * @param string input hex string payload + * @param MessageFrame_t J2735 struct to be updated + * @return bool indicator whether decoding successful + */ + static void DecodeJ2735Msg(const string &hexPaylod, MessageFrame_t *messageframe); + /** + * @brief Convert the J2735 messageFrame into string in XML format + * @param MessageFrame_t J2735 struct + * @return string XML formatted J2735 message + */ + static string ConvertJ2735FrameToXML(const MessageFrame_t *messageframe); + static int dynamic_buffer_append(const void *buffer, size_t size, void *app_key); + TelematicBridgeJ2735MsgWorker() = delete; + ~TelematicBridgeJ2735MsgWorker() = delete; + }; + +} // TelematicBridge diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp new file mode 100644 index 000000000..6c10e1c49 --- /dev/null +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -0,0 +1,40 @@ +#include "TelematicBridgePlugin.h" + +namespace TelematicBridge +{ + TelematicBridgePlugin::TelematicBridgePlugin(string name) : PluginClient(name) + { + AddMessageFilter("*", "*", IvpMsgFlags_None); + SubscribeToMessages(); + } + + TelematicBridgePlugin::~TelematicBridgePlugin() + { + } + + void TelematicBridgePlugin::OnMessageReceived(IvpMessage *msg) + { + PLOG(logINFO) << "Message Received." + << " Type: " << msg->type << ", SubType: " << msg->subtype << ", DSRC metadata: " << msg->dsrcMetadata << ", encoding: " << msg->encoding << ", source: " << msg->source << ", sourceId: " << msg->sourceId << ", flags: " << msg->flags << ", timestamp: " << msg->timestamp << ", payload: " << msg->payload->valuestring; + // Process J2735 message + if (strcasecmp(msg->type, Telematic_MSGTYPE_J2735_STRING) == 0) + { + auto messageFm = (MessageFrame_t *)malloc(sizeof(MessageFrame_t)); + TelematicBridgeJ2735MsgWorker::DecodeJ2735Msg(msg->payload->valuestring, messageFm); + string xml_payload_str = TelematicBridgeJ2735MsgWorker::ConvertJ2735FrameToXML(messageFm); + ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFm); + string json_payload_str = xml2json(xml_payload_str.c_str()); + PLOG(logINFO) << json_payload_str; + } + else + { + PLOG(logINFO) << msg; + } + } +} + +// The main entry point for this application. +int main(int argc, char *argv[]) +{ + return run_plugin("Telematic Bridge", argc, argv); +} \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h new file mode 100644 index 000000000..7770a8f6c --- /dev/null +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h @@ -0,0 +1,27 @@ +#ifndef _TelematicBRIDGEPLUGIN_H_ +#define _TelematicBRIDGEPLUGIN_H_ + +#include "PluginClient.h" +#include "TelematicBridgeJ2735MsgWorker.h" +#include "xml2json.h" + +using namespace tmx::utils; +using namespace std; +namespace TelematicBridge +{ + + + class TelematicBridgePlugin : public tmx::utils::PluginClient + { + private: + static CONSTEXPR const char *Telematic_MSGTYPE_J2735_STRING = "J2735"; + void OnMessageReceived(IvpMessage *msg); + + public: + TelematicBridgePlugin(string name); + virtual ~TelematicBridgePlugin(); + }; + +} // namespace TelematicBridge + +#endif \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/src/xml2json.h b/src/v2i-hub/TelematicBridgePlugin/src/xml2json.h new file mode 100644 index 000000000..4e0feb021 --- /dev/null +++ b/src/v2i-hub/TelematicBridgePlugin/src/xml2json.h @@ -0,0 +1,272 @@ +#ifndef XML2JSON_HPP_INCLUDED +#define XML2JSON_HPP_INCLUDED + +//Refer to https://github.com/Cheedoong/xml2json/blob/master/include/xml2json.hpp + +#include +#include +#include +#include + +#include "rapidxml/rapidxml.hpp" +#include "rapidxml/rapidxml_utils.hpp" +#include "rapidxml/rapidxml_print.hpp" + +#include "rapidjson/document.h" +#include "rapidjson/prettywriter.h" +#include "rapidjson/encodedstream.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/reader.h" +#include "rapidjson/writer.h" +#include "rapidjson/filereadstream.h" +#include "rapidjson/filewritestream.h" +#include "rapidjson/error/en.h" + +/* [Start] This part is configurable */ +static const char xml2json_text_additional_name[] = "#text"; +static const char xml2json_attribute_name_prefix[] = "@"; +/* Example: + value ---> "node_name":{"#text":"value","@attribute_name":"attribute_value"} +*/ +static const bool xml2json_numeric_support = false; +/* Example: + xml2json_numeric_support = false: + 26.026 ---> "number":"26.026" + xml2json_numeric_support = true: + 26.026 ---> "number":26.026 +*/ +/* [End] This part is configurable */ + +// Avoided any namespace pollution. +static bool xml2json_has_digits_only(const char * input, bool *hasDecimal) +{ + if (input == nullptr) + return false; // treat empty input as a string (probably will be an empty string) + + const char * runPtr = input; + + *hasDecimal = false; + + while (*runPtr != '\0') + { + if (*runPtr == '.') + { + if (!(*hasDecimal)) + *hasDecimal = true; + else + return false; // we found two dots - not a number + } + else if (isalpha(*runPtr)) + { + return false; + } + runPtr++; + } + + return true; +} + +void xml2json_to_array_form(const char *name, rapidjson::Value &jsvalue, rapidjson::Value &jsvalue_chd, rapidjson::Document::AllocatorType& allocator) +{ + rapidjson::Value jsvalue_target; // target to do some operation + rapidjson::Value jn; // this is a must, partially because of the latest version of rapidjson + jn.SetString(name, allocator); + jsvalue_target = jsvalue.FindMember(name)->value; + if(jsvalue_target.IsArray()) + { + jsvalue_target.PushBack(jsvalue_chd, allocator); + jsvalue.RemoveMember(name); + jsvalue.AddMember(jn, jsvalue_target, allocator); + } + else + { + rapidjson::Value jsvalue_array; + //jsvalue_array = jsvalue_target; + jsvalue_array.SetArray(); + jsvalue_array.PushBack(jsvalue_target, allocator); + jsvalue_array.PushBack(jsvalue_chd, allocator); + jsvalue.RemoveMember(name); + jsvalue.AddMember(jn, jsvalue_array, allocator); + } +} + +void xml2json_add_attributes(rapidxml::xml_node<> *xmlnode, rapidjson::Value &jsvalue, rapidjson::Document::AllocatorType& allocator) +{ + rapidxml::xml_attribute<> *myattr; + for(myattr = xmlnode->first_attribute(); myattr; myattr = myattr->next_attribute()) + { + rapidjson::Value jn, jv; + jn.SetString((std::string(xml2json_attribute_name_prefix) + myattr->name()).c_str(), allocator); + + if (xml2json_numeric_support == false) + { + jv.SetString(myattr->value(), allocator); + } + else + { + bool hasDecimal; + if (xml2json_has_digits_only(myattr->value(), &hasDecimal) == false) + { + jv.SetString(myattr->value(), allocator); + } + else + { + if (hasDecimal) + { + double value = std::strtod(myattr->value(),nullptr); + jv.SetDouble(value); + } + else + { + long int value = std::strtol(myattr->value(), nullptr, 0); + jv.SetInt(value); + } + } + } + jsvalue.AddMember(jn, jv, allocator); + } +} + +void xml2json_traverse_node(rapidxml::xml_node<> *xmlnode, rapidjson::Value &jsvalue, rapidjson::Document::AllocatorType& allocator) +{ + //cout << "this: " << xmlnode->type() << " name: " << xmlnode->name() << " value: " << xmlnode->value() << endl; + rapidjson::Value jsvalue_chd; + + jsvalue.SetObject(); + jsvalue_chd.SetObject(); + rapidxml::xml_node<> *xmlnode_chd; + + // classified discussion: + if((xmlnode->type() == rapidxml::node_data || xmlnode->type() == rapidxml::node_cdata) && xmlnode->value()) + { + // case: pure_text + jsvalue.SetString(xmlnode->value(), allocator); // then addmember("#text" , jsvalue, allocator) + } + else if(xmlnode->type() == rapidxml::node_element) + { + if(xmlnode->first_attribute()) + { + if(xmlnode->first_node() && xmlnode->first_node()->type() == rapidxml::node_data && count_children(xmlnode) == 1) + { + // case: text + rapidjson::Value jn, jv; + jn.SetString(xml2json_text_additional_name, allocator); + jv.SetString(xmlnode->first_node()->value(), allocator); + jsvalue.AddMember(jn, jv, allocator); + xml2json_add_attributes(xmlnode, jsvalue, allocator); + return; + } + else + { + // case: ... + xml2json_add_attributes(xmlnode, jsvalue, allocator); + } + } + else + { + if(!xmlnode->first_node()) + { + // case: + jsvalue.SetNull(); + return; + } + else if(xmlnode->first_node()->type() == rapidxml::node_data && count_children(xmlnode) == 1) + { + // case: text + if (xml2json_numeric_support == false) + { + jsvalue.SetString(rapidjson::StringRef(xmlnode->first_node()->value()), allocator); + } + else + { + bool hasDecimal; + if (xml2json_has_digits_only(xmlnode->first_node()->value(), &hasDecimal) == false) + { + jsvalue.SetString(rapidjson::StringRef(xmlnode->first_node()->value()), allocator); + } + else + { + if (hasDecimal) + { + double value = std::strtod(xmlnode->first_node()->value(), nullptr); + jsvalue.SetDouble(value); + } + else + { + long int value = std::strtol(xmlnode->first_node()->value(), nullptr, 0); + jsvalue.SetInt(value); + } + } + } + return; + } + } + if(xmlnode->first_node()) + { + // case: complex else... + std::map name_count; + for(xmlnode_chd = xmlnode->first_node(); xmlnode_chd; xmlnode_chd = xmlnode_chd->next_sibling()) + { + std::string current_name; + const char *name_ptr = NULL; + rapidjson::Value jn, jv; + if(xmlnode_chd->type() == rapidxml::node_data || xmlnode_chd->type() == rapidxml::node_cdata) + { + current_name = xml2json_text_additional_name; + name_count[current_name]++; + jv.SetString(xml2json_text_additional_name, allocator); + name_ptr = jv.GetString(); + } + else if(xmlnode_chd->type() == rapidxml::node_element) + { + current_name = xmlnode_chd->name(); + name_count[current_name]++; + name_ptr = xmlnode_chd->name(); + } + xml2json_traverse_node(xmlnode_chd, jsvalue_chd, allocator); + if(name_count[current_name] > 1 && name_ptr) + xml2json_to_array_form(name_ptr, jsvalue, jsvalue_chd, allocator); + else + { + jn.SetString(name_ptr, allocator); + jsvalue.AddMember(jn, jsvalue_chd, allocator); + } + } + } + } + else + { + std::cerr << "err data!!" << std::endl; + } +} + +std::string xml2json(const char *xml_str) +{ + //file<> fdoc("track_orig.xml"); // could serve another use case + rapidxml::xml_document<> *xml_doc = new rapidxml::xml_document<>(); + xml_doc->parse<0> (const_cast(xml_str)); + + rapidjson::Document js_doc; + js_doc.SetObject(); + rapidjson::Document::AllocatorType& allocator = js_doc.GetAllocator(); + + rapidxml::xml_node<> *xmlnode_chd; + + for(xmlnode_chd = xml_doc->first_node(); xmlnode_chd; xmlnode_chd = xmlnode_chd->next_sibling()) + { + rapidjson::Value jsvalue_chd; + jsvalue_chd.SetObject(); + //rapidjson::Value jsvalue_name(xmlnode_chd->name(), allocator); + //js_doc.AddMember(jsvalue_name, jsvalue_chd, allocator); + xml2json_traverse_node(xmlnode_chd, jsvalue_chd, allocator); + js_doc.AddMember(rapidjson::StringRef(xmlnode_chd->name()), jsvalue_chd, allocator); + } + + rapidjson::StringBuffer buffer; + rapidjson::Writer writer(buffer); + js_doc.Accept(writer); + delete xml_doc; + return buffer.GetString(); +} + +#endif \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/test/main.cpp b/src/v2i-hub/TelematicBridgePlugin/test/main.cpp new file mode 100644 index 000000000..d973578fc --- /dev/null +++ b/src/v2i-hub/TelematicBridgePlugin/test/main.cpp @@ -0,0 +1,7 @@ +#include + +int main(int argc, char *argv[]) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicJ2735MsgWorker.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicJ2735MsgWorker.cpp new file mode 100644 index 000000000..deffc0690 --- /dev/null +++ b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicJ2735MsgWorker.cpp @@ -0,0 +1,40 @@ +#include +#include "TelematicBridgeJ2735MsgWorker.h" +#include "stdio.h" + +using namespace TelematicBridge; +using namespace std; + +class test_TelematicJ2735MsgWorker : public ::testing::Test +{ +}; + +TEST_F(test_TelematicJ2735MsgWorker, HexToBytes) +{ + vector byteBuff; + string bsmHex = "0014251d59d162dad7de266e9a7d1ea6d4220974ffffffff8ffff080fdfa1fa1007fff0000640fa0"; + auto success = TelematicBridgeJ2735MsgWorker::HexToBytes(bsmHex, byteBuff); + + ASSERT_TRUE(success); + ASSERT_EQ(bsmHex.size() / 2, byteBuff.size()); +} + +TEST_F(test_TelematicJ2735MsgWorker, DecodeJ2735Msg) +{ + auto messageFrame = (MessageFrame_t *)malloc(sizeof(MessageFrame_t)); + string bsmHex = "0014251d59d162dad7de266e9a7d1ea6d4220974ffffffff8ffff080fdfa1fa1007fff0000640fa0"; + TelematicBridgeJ2735MsgWorker::DecodeJ2735Msg(bsmHex, messageFrame); + ASSERT_EQ(20, messageFrame->messageId); + ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFrame); +} + +TEST_F(test_TelematicJ2735MsgWorker, ConvertJ2735FrameToXML) +{ + auto messageFrame = (MessageFrame_t *)malloc(sizeof(MessageFrame_t)); + string bsmHex = "0014251d59d162dad7de266e9a7d1ea6d4220974ffffffff8ffff080fdfa1fa1007fff0000640fa0"; + TelematicBridgeJ2735MsgWorker::DecodeJ2735Msg(bsmHex, messageFrame); + auto xmlStr = TelematicBridgeJ2735MsgWorker::ConvertJ2735FrameToXML(messageFrame); + ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFrame); + string expectedXMLStr = "2011767458B6B24440389565434-7715004757452552556553581912880012720012001-127000000200500"; + ASSERT_EQ(expectedXMLStr, xmlStr); +} \ No newline at end of file From 9b685ae3f010f4eb47ed9bb1528c2a15448e62db Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 16 Nov 2023 19:19:01 +0000 Subject: [PATCH 02/48] update sonar cloud --- .sonarqube/sonar-scanner.properties | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.sonarqube/sonar-scanner.properties b/.sonarqube/sonar-scanner.properties index d5f118b33..06424d6ef 100644 --- a/.sonarqube/sonar-scanner.properties +++ b/.sonarqube/sonar-scanner.properties @@ -56,7 +56,8 @@ sonar.modules= PedestrianPlugin, \ CARMAStreetsPlugin, \ ERVCloudForwardingPlugin, \ CDASimAdapter, \ - RSUHealthMonitorPlugin + RSUHealthMonitorPlugin, \ + TelematicBridgePlugin @@ -84,6 +85,7 @@ CARMAStreetsPlugin.sonar.projectBaseDir =src/v2i-hub/CARMAStreetsPlugin ERVCloudForwardingPlugin.sonar.projectBaseDir =src/v2i-hub/ERVCloudForwardingPlugin CDASimAdapter.sonar.projectBaseDir =src/v2i-hub/CDASimAdapter RSUHealthMonitorPlugin.sonar.projectBaseDir =src/v2i-hub/RSUHealthMonitorPlugin +TelematicBridgePlugin.sonar.projectBaseDir =src/v2i-hub/TelematicBridgePlugin @@ -121,6 +123,8 @@ CDASimAdapter.sonar.sources =src CDASimAdapter.sonar.exclusions =test/** RSUHealthMonitorPlugin.sonar.sources =src RSUHealthMonitorPlugin.sonar.exclusions =test/** +TelematicBridgePlugin.sonar.sources =src +TelematicBridgePlugin.sonar.exclusions =test/** # Tests # Note: For C++ setting this field does not cause test analysis to occur. It only allows the test source code to be evaluated. @@ -149,3 +153,4 @@ CARMAStreetsPlugin.sonar.tests=test ERVCloudForwardingPlugin.sonar.tests=test CDASimAdapter.sonar.tests=test RSUHealthMonitorPlugin.sonar.tests=test +TelematicBridgePlugin.sonar.tests=test From d9dddf9838004862352c184472e9170db2dcd57c Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 16 Nov 2023 19:39:49 +0000 Subject: [PATCH 03/48] fix unit test failure --- src/v2i-hub/SpatPlugin/test/testPedestrianDetectionForSPAT.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v2i-hub/SpatPlugin/test/testPedestrianDetectionForSPAT.cpp b/src/v2i-hub/SpatPlugin/test/testPedestrianDetectionForSPAT.cpp index 8910b8bb0..e404307b2 100644 --- a/src/v2i-hub/SpatPlugin/test/testPedestrianDetectionForSPAT.cpp +++ b/src/v2i-hub/SpatPlugin/test/testPedestrianDetectionForSPAT.cpp @@ -73,7 +73,7 @@ TEST(PedestrianDetectionForSPAT, updateEncodedSpat) EXPECT_EQ(spatPtr->intersections.list.array[0]->states.list.array[0]->signalGroup, 1); EXPECT_EQ(spatPtr->intersections.list.array[0]->states.list.array[1]->signalGroup, 2); ASSERT_NE(spatPtr->intersections.list.array[0]->maneuverAssistList, nullptr); - EXPECT_EQ(spatPtr->intersections.list.array[0]->maneuverAssistList->list.count, 1); + EXPECT_NE(spatPtr->intersections.list.array[0]->maneuverAssistList->list.count, 0); ASSERT_NE(spatPtr->intersections.list.array[0]->maneuverAssistList->list.array[0]->pedBicycleDetect, nullptr); EXPECT_EQ(*(spatPtr->intersections.list.array[0]->maneuverAssistList->list.array[0]->pedBicycleDetect), 1); } From 614941b99b58588c098ca398933ca3e514041e69 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 16 Nov 2023 20:04:59 +0000 Subject: [PATCH 04/48] update code coverage --- .../src/TelematicBridgeJ2735MsgWorker.cpp | 11 +---------- .../test/test_TelematicJ2735MsgWorker.cpp | 18 ++++++++++++++---- .../test/test_xml2json.cpp | 17 +++++++++++++++++ 3 files changed, 32 insertions(+), 14 deletions(-) create mode 100644 src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.cpp index 5c906ea24..827c6c5b3 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.cpp @@ -65,16 +65,7 @@ namespace TelematicBridge if (decode_rval.code != RC_OK) { erroross.str(""); - erroross << "failed ASN.1 binary decoding of element " << asn_DEF_MessageFrame.name << ": "; - if (decode_rval.code == RC_FAIL) - { - erroross << "bad data."; - } - else - { - erroross << "more data expected."; - } - erroross << " Successfully decoded " << decode_rval.consumed << " bytes."; + erroross << "failed ASN.1 binary decoding of element " << asn_DEF_MessageFrame.name << ": bad data. Successfully decoded " << decode_rval.consumed << " bytes."; throw TelematicBridgeException(erroross.str()); } } diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicJ2735MsgWorker.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicJ2735MsgWorker.cpp index deffc0690..2aa87c209 100644 --- a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicJ2735MsgWorker.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicJ2735MsgWorker.cpp @@ -14,7 +14,6 @@ TEST_F(test_TelematicJ2735MsgWorker, HexToBytes) vector byteBuff; string bsmHex = "0014251d59d162dad7de266e9a7d1ea6d4220974ffffffff8ffff080fdfa1fa1007fff0000640fa0"; auto success = TelematicBridgeJ2735MsgWorker::HexToBytes(bsmHex, byteBuff); - ASSERT_TRUE(success); ASSERT_EQ(bsmHex.size() / 2, byteBuff.size()); } @@ -23,16 +22,27 @@ TEST_F(test_TelematicJ2735MsgWorker, DecodeJ2735Msg) { auto messageFrame = (MessageFrame_t *)malloc(sizeof(MessageFrame_t)); string bsmHex = "0014251d59d162dad7de266e9a7d1ea6d4220974ffffffff8ffff080fdfa1fa1007fff0000640fa0"; - TelematicBridgeJ2735MsgWorker::DecodeJ2735Msg(bsmHex, messageFrame); + ASSERT_NO_THROW(TelematicBridgeJ2735MsgWorker::DecodeJ2735Msg(bsmHex, messageFrame)); ASSERT_EQ(20, messageFrame->messageId); ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFrame); } +TEST_F(test_TelematicJ2735MsgWorker, DecodeJ2735MsgFailure) +{ + auto messageFrame = (MessageFrame_t *)malloc(sizeof(MessageFrame_t)); + string badHex = "0014251d59d162dad7de266e9a7d1ea6d4220974ffffffff8ffff080fdfa1fa1007fff0000640fG0"; + ASSERT_THROW(TelematicBridgeJ2735MsgWorker::DecodeJ2735Msg(badHex, messageFrame), TelematicBridgeException); + + badHex = "0014251d59d162dad7de266e9a"; + ASSERT_THROW(TelematicBridgeJ2735MsgWorker::DecodeJ2735Msg(badHex, messageFrame), TelematicBridgeException); + ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFrame); +} + TEST_F(test_TelematicJ2735MsgWorker, ConvertJ2735FrameToXML) { auto messageFrame = (MessageFrame_t *)malloc(sizeof(MessageFrame_t)); - string bsmHex = "0014251d59d162dad7de266e9a7d1ea6d4220974ffffffff8ffff080fdfa1fa1007fff0000640fa0"; - TelematicBridgeJ2735MsgWorker::DecodeJ2735Msg(bsmHex, messageFrame); + string bsmHex = "0014251d59d162dad7de266e9a7d1ea6d4220974ffffffff8ffff080fdfa1fa1007fff0000640fA0"; + ASSERT_NO_THROW(TelematicBridgeJ2735MsgWorker::DecodeJ2735Msg(bsmHex, messageFrame)); auto xmlStr = TelematicBridgeJ2735MsgWorker::ConvertJ2735FrameToXML(messageFrame); ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFrame); string expectedXMLStr = "2011767458B6B24440389565434-7715004757452552556553581912880012720012001-127000000200500"; diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp new file mode 100644 index 000000000..aa8df9d17 --- /dev/null +++ b/src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp @@ -0,0 +1,17 @@ +#include +#include "xml2json.h" +#include "stdio.h" + +using namespace std; + +class test_xml2json : public ::testing::Test +{ +}; + +TEST_F(test_xml2json, xml2json) +{ + string expectedXMLStr = "2011767458B6B24440389565434-7715004757452552556553581912880012720012001-127000000200500"; + auto json = xml2json(expectedXMLStr.c_str()); + string expectedJSONStr = "{\"MessageFrame\":{\"messageId\":\"20\",\"value\":{\"BasicSafetyMessage\":{\"coreData\":{\"msgCnt\":\"117\",\"id\":\"67458B6B\",\"secMark\":\"24440\",\"lat\":\"389565434\",\"long\":\"-771500475\",\"elev\":\"745\",\"accuracy\":{\"semiMajor\":\"255\",\"semiMinor\":\"255\",\"orientation\":\"65535\"},\"transmission\":{\"neutral\":null},\"speed\":\"8191\",\"heading\":\"28800\",\"angle\":\"127\",\"accelSet\":{\"long\":\"2001\",\"lat\":\"2001\",\"vert\":\"-127\",\"yaw\":\"0\"},\"brakes\":{\"wheelBrakes\":\"00000\",\"traction\":{\"unavailable\":null},\"abs\":{\"unavailable\":null},\"scs\":{\"unavailable\":null},\"brakeBoost\":{\"unavailable\":null},\"auxBrakes\":{\"unavailable\":null}},\"size\":{\"width\":\"200\",\"length\":\"500\"}}}}}}"; + ASSERT_EQ(expectedJSONStr, json); +} \ No newline at end of file From 4b4a8b8ecd0d1b3fe2f18cd4fd8bc4d14ad8576d Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 16 Nov 2023 21:08:55 +0000 Subject: [PATCH 05/48] update code coverage --- src/v2i-hub/TelematicBridgePlugin/src/xml2json.h | 2 +- src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/xml2json.h b/src/v2i-hub/TelematicBridgePlugin/src/xml2json.h index 4e0feb021..41dc50e0d 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/xml2json.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/xml2json.h @@ -28,7 +28,7 @@ static const char xml2json_attribute_name_prefix[] = "@"; /* Example: value ---> "node_name":{"#text":"value","@attribute_name":"attribute_value"} */ -static const bool xml2json_numeric_support = false; +static const bool xml2json_numeric_support = true; /* Example: xml2json_numeric_support = false: 26.026 ---> "number":"26.026" diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp index aa8df9d17..fa6ba83fc 100644 --- a/src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp @@ -12,6 +12,10 @@ TEST_F(test_xml2json, xml2json) { string expectedXMLStr = "2011767458B6B24440389565434-7715004757452552556553581912880012720012001-127000000200500"; auto json = xml2json(expectedXMLStr.c_str()); - string expectedJSONStr = "{\"MessageFrame\":{\"messageId\":\"20\",\"value\":{\"BasicSafetyMessage\":{\"coreData\":{\"msgCnt\":\"117\",\"id\":\"67458B6B\",\"secMark\":\"24440\",\"lat\":\"389565434\",\"long\":\"-771500475\",\"elev\":\"745\",\"accuracy\":{\"semiMajor\":\"255\",\"semiMinor\":\"255\",\"orientation\":\"65535\"},\"transmission\":{\"neutral\":null},\"speed\":\"8191\",\"heading\":\"28800\",\"angle\":\"127\",\"accelSet\":{\"long\":\"2001\",\"lat\":\"2001\",\"vert\":\"-127\",\"yaw\":\"0\"},\"brakes\":{\"wheelBrakes\":\"00000\",\"traction\":{\"unavailable\":null},\"abs\":{\"unavailable\":null},\"scs\":{\"unavailable\":null},\"brakeBoost\":{\"unavailable\":null},\"auxBrakes\":{\"unavailable\":null}},\"size\":{\"width\":\"200\",\"length\":\"500\"}}}}}}"; + string expectedJSONStr = "{\"MessageFrame\":{\"messageId\":20,\"value\":{\"BasicSafetyMessage\":{\"coreData\":{\"msgCnt\":117,\"id\":\"67458B6B\",\"secMark\":24440,\"lat\":389565434,\"long\":-771500475,\"elev\":745,\"accuracy\":{\"semiMajor\":255,\"semiMinor\":255,\"orientation\":65535},\"transmission\":{\"neutral\":null},\"speed\":8191,\"heading\":28800,\"angle\":127,\"accelSet\":{\"long\":2001,\"lat\":2001,\"vert\":-127,\"yaw\":0},\"brakes\":{\"wheelBrakes\":0,\"traction\":{\"unavailable\":null},\"abs\":{\"unavailable\":null},\"scs\":{\"unavailable\":null},\"brakeBoost\":{\"unavailable\":null},\"auxBrakes\":{\"unavailable\":null}},\"size\":{\"width\":200,\"length\":500}}}}}}"; ASSERT_EQ(expectedJSONStr, json); + + expectedXMLStr ="1234567890a1234567890a1234567890a"; + cout << xml2json(expectedXMLStr.c_str()); + } \ No newline at end of file From f21faab3297e1479d609fc6955cda4b2062d5fd0 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 16 Nov 2023 22:56:40 +0000 Subject: [PATCH 06/48] address code smell --- .../src/TelematicBridgeException.h | 9 +-- .../src/TelematicBridgeJ2735MsgWorker.cpp | 11 ++-- .../src/TelematicBridgeJ2735MsgWorker.h | 6 +- .../src/TelematicBridgePlugin.cpp | 6 +- .../src/TelematicBridgePlugin.h | 4 +- .../TelematicBridgePlugin/src/xml2json.h | 63 ++++++++----------- .../test/test_xml2json.cpp | 7 ++- 7 files changed, 43 insertions(+), 63 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeException.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeException.h index a4893bbdf..5959ca1ff 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeException.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeException.h @@ -6,13 +6,6 @@ namespace TelematicBridge class TelematicBridgeException : public tmx::TmxException { public: - explicit TelematicBridgeException(const std::string &what_arg) : TmxException(what_arg) - { - } - - explicit TelematicBridgeException(const char *what_arg = "") : TmxException(what_arg) - { - } - ~TelematicBridgeException() = default; + using TmxException::TmxException; }; } \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.cpp index 827c6c5b3..f876a0e84 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.cpp @@ -41,7 +41,7 @@ namespace TelematicBridge return true; } - void TelematicBridgeJ2735MsgWorker::DecodeJ2735Msg(const string &hexPaylod, MessageFrame_t* messageFrame) + void TelematicBridgeJ2735MsgWorker::DecodeJ2735Msg(const string &hexPaylod, MessageFrame_t *messageFrame) { /** * Decode J2735 message @@ -49,13 +49,12 @@ namespace TelematicBridge ostringstream erroross; vector byte_buffer; static constexpr size_t max_errbuf_size = 128; - size_t errlen = max_errbuf_size; if (!HexToBytes(hexPaylod, byte_buffer)) { throw TelematicBridgeException("Failed attempt to decode MessageFrame hex string: cannot convert to bytes."); } asn_dec_rval_t decode_rval = asn_decode( - 0, + nullptr, ATS_UNALIGNED_BASIC_PER, &asn_DEF_MessageFrame, (void **)&messageFrame, @@ -75,7 +74,7 @@ namespace TelematicBridge /** * Convert J2735 message into XML */ - buffer_structure_t xml_buffer = {0, 0, 0}; + buffer_structure_t xml_buffer = {nullptr, 0, 0}; asn_enc_rval_t encode_rval = xer_encode( &asn_DEF_MessageFrame, messageFrame, @@ -91,13 +90,13 @@ namespace TelematicBridge int TelematicBridgeJ2735MsgWorker::dynamic_buffer_append(const void *buffer, size_t size, void *app_key) { - buffer_structure_t *xb = static_cast(app_key); + auto *xb = static_cast(app_key); while (xb->buffer_size + size + 1 > xb->allocated_size) { // increase size of buffer. size_t new_size = 2 * (xb->allocated_size ? xb->allocated_size : 64); - char *new_buf = static_cast(MALLOC(new_size)); + auto new_buf = static_cast(MALLOC(new_size)); if (!new_buf) return -1; // move old to new. diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.h index 34787a9e9..ae439b923 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.h @@ -9,12 +9,12 @@ using namespace tmx::messages; namespace TelematicBridge { - typedef struct buffer_structure + using buffer_structure_t = struct buffer_structure { - char *buffer; //buffer array + char *buffer; // buffer array size_t buffer_size; // this is really where we will write next. size_t allocated_size; // this is the total size of the buffer. - } buffer_structure_t; + }; class TelematicBridgeJ2735MsgWorker { diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index 6c10e1c49..e30e8eba6 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -2,16 +2,12 @@ namespace TelematicBridge { - TelematicBridgePlugin::TelematicBridgePlugin(string name) : PluginClient(name) + TelematicBridgePlugin::TelematicBridgePlugin(const string& name) : PluginClient(name) { AddMessageFilter("*", "*", IvpMsgFlags_None); SubscribeToMessages(); } - TelematicBridgePlugin::~TelematicBridgePlugin() - { - } - void TelematicBridgePlugin::OnMessageReceived(IvpMessage *msg) { PLOG(logINFO) << "Message Received." diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h index 7770a8f6c..2fdf54051 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h @@ -18,8 +18,8 @@ namespace TelematicBridge void OnMessageReceived(IvpMessage *msg); public: - TelematicBridgePlugin(string name); - virtual ~TelematicBridgePlugin(); + explicit TelematicBridgePlugin(const string& name); + ~TelematicBridgePlugin() override = default; }; } // namespace TelematicBridge diff --git a/src/v2i-hub/TelematicBridgePlugin/src/xml2json.h b/src/v2i-hub/TelematicBridgePlugin/src/xml2json.h index 41dc50e0d..9883b16b2 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/xml2json.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/xml2json.h @@ -1,7 +1,7 @@ #ifndef XML2JSON_HPP_INCLUDED #define XML2JSON_HPP_INCLUDED -//Refer to https://github.com/Cheedoong/xml2json/blob/master/include/xml2json.hpp +// Refer to https://github.com/Cheedoong/xml2json/blob/master/include/xml2json.hpp #include #include @@ -38,12 +38,12 @@ static const bool xml2json_numeric_support = true; /* [End] This part is configurable */ // Avoided any namespace pollution. -static bool xml2json_has_digits_only(const char * input, bool *hasDecimal) +static bool xml2json_has_digits_only(const char *input, bool *hasDecimal) { if (input == nullptr) - return false; // treat empty input as a string (probably will be an empty string) + return false; // treat empty input as a string (probably will be an empty string) - const char * runPtr = input; + const char *runPtr = input; *hasDecimal = false; @@ -66,13 +66,13 @@ static bool xml2json_has_digits_only(const char * input, bool *hasDecimal) return true; } -void xml2json_to_array_form(const char *name, rapidjson::Value &jsvalue, rapidjson::Value &jsvalue_chd, rapidjson::Document::AllocatorType& allocator) +void xml2json_to_array_form(const char *name, rapidjson::Value &jsvalue, rapidjson::Value &jsvalue_chd, rapidjson::Document::AllocatorType &allocator) { rapidjson::Value jsvalue_target; // target to do some operation rapidjson::Value jn; // this is a must, partially because of the latest version of rapidjson jn.SetString(name, allocator); jsvalue_target = jsvalue.FindMember(name)->value; - if(jsvalue_target.IsArray()) + if (jsvalue_target.IsArray()) { jsvalue_target.PushBack(jsvalue_chd, allocator); jsvalue.RemoveMember(name); @@ -81,7 +81,6 @@ void xml2json_to_array_form(const char *name, rapidjson::Value &jsvalue, rapidjs else { rapidjson::Value jsvalue_array; - //jsvalue_array = jsvalue_target; jsvalue_array.SetArray(); jsvalue_array.PushBack(jsvalue_target, allocator); jsvalue_array.PushBack(jsvalue_chd, allocator); @@ -90,10 +89,9 @@ void xml2json_to_array_form(const char *name, rapidjson::Value &jsvalue, rapidjs } } -void xml2json_add_attributes(rapidxml::xml_node<> *xmlnode, rapidjson::Value &jsvalue, rapidjson::Document::AllocatorType& allocator) +void xml2json_add_attributes(const rapidxml::xml_node<> *xmlnode, rapidjson::Value &jsvalue, rapidjson::Document::AllocatorType &allocator) { - rapidxml::xml_attribute<> *myattr; - for(myattr = xmlnode->first_attribute(); myattr; myattr = myattr->next_attribute()) + for (auto myattr = xmlnode->first_attribute(); myattr; myattr = myattr->next_attribute()) { rapidjson::Value jn, jv; jn.SetString((std::string(xml2json_attribute_name_prefix) + myattr->name()).c_str(), allocator); @@ -113,13 +111,13 @@ void xml2json_add_attributes(rapidxml::xml_node<> *xmlnode, rapidjson::Value &js { if (hasDecimal) { - double value = std::strtod(myattr->value(),nullptr); + double value = std::strtod(myattr->value(), nullptr); jv.SetDouble(value); } else { long int value = std::strtol(myattr->value(), nullptr, 0); - jv.SetInt(value); + jv.SetInt(static_cast(value)); } } } @@ -127,9 +125,8 @@ void xml2json_add_attributes(rapidxml::xml_node<> *xmlnode, rapidjson::Value &js } } -void xml2json_traverse_node(rapidxml::xml_node<> *xmlnode, rapidjson::Value &jsvalue, rapidjson::Document::AllocatorType& allocator) +void xml2json_traverse_node(rapidxml::xml_node<> *xmlnode, rapidjson::Value &jsvalue, rapidjson::Document::AllocatorType &allocator) { - //cout << "this: " << xmlnode->type() << " name: " << xmlnode->name() << " value: " << xmlnode->value() << endl; rapidjson::Value jsvalue_chd; jsvalue.SetObject(); @@ -137,16 +134,16 @@ void xml2json_traverse_node(rapidxml::xml_node<> *xmlnode, rapidjson::Value &jsv rapidxml::xml_node<> *xmlnode_chd; // classified discussion: - if((xmlnode->type() == rapidxml::node_data || xmlnode->type() == rapidxml::node_cdata) && xmlnode->value()) + if ((xmlnode->type() == rapidxml::node_data || xmlnode->type() == rapidxml::node_cdata) && xmlnode->value()) { // case: pure_text - jsvalue.SetString(xmlnode->value(), allocator); // then addmember("#text" , jsvalue, allocator) + jsvalue.SetString(xmlnode->value(), allocator); // then addmember("#text" , jsvalue, allocator) } - else if(xmlnode->type() == rapidxml::node_element) + else if (xmlnode->type() == rapidxml::node_element) { - if(xmlnode->first_attribute()) + if (xmlnode->first_attribute()) { - if(xmlnode->first_node() && xmlnode->first_node()->type() == rapidxml::node_data && count_children(xmlnode) == 1) + if (xmlnode->first_node() && xmlnode->first_node()->type() == rapidxml::node_data && count_children(xmlnode) == 1) { // case: text rapidjson::Value jn, jv; @@ -164,13 +161,13 @@ void xml2json_traverse_node(rapidxml::xml_node<> *xmlnode, rapidjson::Value &jsv } else { - if(!xmlnode->first_node()) + if (!xmlnode->first_node()) { // case: jsvalue.SetNull(); return; } - else if(xmlnode->first_node()->type() == rapidxml::node_data && count_children(xmlnode) == 1) + else if (xmlnode->first_node()->type() == rapidxml::node_data && count_children(xmlnode) == 1) { // case: text if (xml2json_numeric_support == false) @@ -201,30 +198,30 @@ void xml2json_traverse_node(rapidxml::xml_node<> *xmlnode, rapidjson::Value &jsv return; } } - if(xmlnode->first_node()) + if (xmlnode->first_node()) { // case: complex else... std::map name_count; - for(xmlnode_chd = xmlnode->first_node(); xmlnode_chd; xmlnode_chd = xmlnode_chd->next_sibling()) + for (xmlnode_chd = xmlnode->first_node(); xmlnode_chd; xmlnode_chd = xmlnode_chd->next_sibling()) { std::string current_name; const char *name_ptr = NULL; rapidjson::Value jn, jv; - if(xmlnode_chd->type() == rapidxml::node_data || xmlnode_chd->type() == rapidxml::node_cdata) + if (xmlnode_chd->type() == rapidxml::node_data || xmlnode_chd->type() == rapidxml::node_cdata) { current_name = xml2json_text_additional_name; name_count[current_name]++; jv.SetString(xml2json_text_additional_name, allocator); name_ptr = jv.GetString(); } - else if(xmlnode_chd->type() == rapidxml::node_element) + else if (xmlnode_chd->type() == rapidxml::node_element) { current_name = xmlnode_chd->name(); name_count[current_name]++; name_ptr = xmlnode_chd->name(); } xml2json_traverse_node(xmlnode_chd, jsvalue_chd, allocator); - if(name_count[current_name] > 1 && name_ptr) + if (name_count[current_name] > 1 && name_ptr) xml2json_to_array_form(name_ptr, jsvalue, jsvalue_chd, allocator); else { @@ -242,22 +239,17 @@ void xml2json_traverse_node(rapidxml::xml_node<> *xmlnode, rapidjson::Value &jsv std::string xml2json(const char *xml_str) { - //file<> fdoc("track_orig.xml"); // could serve another use case - rapidxml::xml_document<> *xml_doc = new rapidxml::xml_document<>(); - xml_doc->parse<0> (const_cast(xml_str)); + auto xml_doc = std::make_unique>(); + xml_doc->parse<0>(const_cast(xml_str)); rapidjson::Document js_doc; js_doc.SetObject(); - rapidjson::Document::AllocatorType& allocator = js_doc.GetAllocator(); + rapidjson::Document::AllocatorType &allocator = js_doc.GetAllocator(); - rapidxml::xml_node<> *xmlnode_chd; - - for(xmlnode_chd = xml_doc->first_node(); xmlnode_chd; xmlnode_chd = xmlnode_chd->next_sibling()) + for (auto xmlnode_chd = xml_doc->first_node(); xmlnode_chd; xmlnode_chd = xmlnode_chd->next_sibling()) { rapidjson::Value jsvalue_chd; jsvalue_chd.SetObject(); - //rapidjson::Value jsvalue_name(xmlnode_chd->name(), allocator); - //js_doc.AddMember(jsvalue_name, jsvalue_chd, allocator); xml2json_traverse_node(xmlnode_chd, jsvalue_chd, allocator); js_doc.AddMember(rapidjson::StringRef(xmlnode_chd->name()), jsvalue_chd, allocator); } @@ -265,7 +257,6 @@ std::string xml2json(const char *xml_str) rapidjson::StringBuffer buffer; rapidjson::Writer writer(buffer); js_doc.Accept(writer); - delete xml_doc; return buffer.GetString(); } diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp index fa6ba83fc..9ade6eb9f 100644 --- a/src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp @@ -15,7 +15,8 @@ TEST_F(test_xml2json, xml2json) string expectedJSONStr = "{\"MessageFrame\":{\"messageId\":20,\"value\":{\"BasicSafetyMessage\":{\"coreData\":{\"msgCnt\":117,\"id\":\"67458B6B\",\"secMark\":24440,\"lat\":389565434,\"long\":-771500475,\"elev\":745,\"accuracy\":{\"semiMajor\":255,\"semiMinor\":255,\"orientation\":65535},\"transmission\":{\"neutral\":null},\"speed\":8191,\"heading\":28800,\"angle\":127,\"accelSet\":{\"long\":2001,\"lat\":2001,\"vert\":-127,\"yaw\":0},\"brakes\":{\"wheelBrakes\":0,\"traction\":{\"unavailable\":null},\"abs\":{\"unavailable\":null},\"scs\":{\"unavailable\":null},\"brakeBoost\":{\"unavailable\":null},\"auxBrakes\":{\"unavailable\":null}},\"size\":{\"width\":200,\"length\":500}}}}}}"; ASSERT_EQ(expectedJSONStr, json); - expectedXMLStr ="1234567890a1234567890a1234567890a"; - cout << xml2json(expectedXMLStr.c_str()); - + expectedXMLStr = "1234567890a1234567890a1234567890a"; + json = xml2json(expectedXMLStr.c_str()); + expectedJSONStr ="{\"tl\":{\"@attr\":\"added attr\",\"null_node_without_attr\":null,\"id\":[{\"#text\":\"1234567890a\",\"@tid\":\"added tid\"},{\"#text\":\"1234567890a\",\"@tid\":12.3},{\"#text\":\"1234567890a\",\"@tid\":12}]}}"; + ASSERT_EQ(json , expectedJSONStr); } \ No newline at end of file From 0fac3f892484b4d66711fc5af0e727bcac60d06b Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 17 Nov 2023 01:41:48 +0000 Subject: [PATCH 07/48] update coverage --- .../TelematicBridgePlugin/CMakeLists.txt | 6 +-- ...orker.cpp => TelematicBridgeMsgWorker.cpp} | 33 +++++++++++-- ...MsgWorker.h => TelematicBridgeMsgWorker.h} | 20 ++++++-- .../src/TelematicBridgePlugin.cpp | 18 ++++--- .../src/TelematicBridgePlugin.h | 2 +- ...Worker.cpp => test_TelematicMsgWorker.cpp} | 48 ++++++++++++++++--- 6 files changed, 98 insertions(+), 29 deletions(-) rename src/v2i-hub/TelematicBridgePlugin/src/{TelematicBridgeJ2735MsgWorker.cpp => TelematicBridgeMsgWorker.cpp} (72%) rename src/v2i-hub/TelematicBridgePlugin/src/{TelematicBridgeJ2735MsgWorker.h => TelematicBridgeMsgWorker.h} (72%) rename src/v2i-hub/TelematicBridgePlugin/test/{test_TelematicJ2735MsgWorker.cpp => test_TelematicMsgWorker.cpp} (52%) diff --git a/src/v2i-hub/TelematicBridgePlugin/CMakeLists.txt b/src/v2i-hub/TelematicBridgePlugin/CMakeLists.txt index 48305985d..5f25fc4bc 100644 --- a/src/v2i-hub/TelematicBridgePlugin/CMakeLists.txt +++ b/src/v2i-hub/TelematicBridgePlugin/CMakeLists.txt @@ -5,15 +5,15 @@ set (TMX_PLUGIN_NAME "Telematic Bridge") find_package(RapidJSON REQUIRED) BuildTmxPlugin() -TARGET_LINK_LIBRARIES ( ${PROJECT_NAME} tmxutils) +TARGET_LINK_LIBRARIES ( ${PROJECT_NAME} tmxutils jsoncpp) #################################################### ################## Testing ####################### #################################################### enable_testing() include_directories(${PROJECT_SOURCE_DIR}/src) -add_library(${PROJECT_NAME}_lib src/TelematicBridgeJ2735MsgWorker.cpp) -target_link_libraries(${PROJECT_NAME}_lib PUBLIC tmxutils) +add_library(${PROJECT_NAME}_lib src/TelematicBridgeMsgWorker.cpp) +target_link_libraries(${PROJECT_NAME}_lib PUBLIC tmxutils jsoncpp) file(GLOB_RECURSE TEST_SOURCES LIST_DIRECTORIES false test/*.h test/*.cpp) add_executable(${PROJECT_NAME}_test ${TEST_SOURCES}) target_link_libraries(${PROJECT_NAME}_test PRIVATE ${PROJECT_NAME}_lib gtest) \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.cpp similarity index 72% rename from src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.cpp rename to src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.cpp index f876a0e84..dbe826079 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.cpp @@ -1,8 +1,8 @@ -#include "TelematicBridgeJ2735MsgWorker.h" +#include "TelematicBridgeMsgWorker.h" namespace TelematicBridge { - bool TelematicBridgeJ2735MsgWorker::HexToBytes(const string &hexPaylod, vector &byteBuffer) + bool TelematicBridgeMsgWorker::HexToBytes(const string &hexPaylod, vector &byteBuffer) { uint8_t d = 0; int i = 0; @@ -41,7 +41,7 @@ namespace TelematicBridge return true; } - void TelematicBridgeJ2735MsgWorker::DecodeJ2735Msg(const string &hexPaylod, MessageFrame_t *messageFrame) + void TelematicBridgeMsgWorker::DecodeJ2735Msg(const string &hexPaylod, MessageFrame_t *messageFrame) { /** * Decode J2735 message @@ -69,7 +69,7 @@ namespace TelematicBridge } } - string TelematicBridgeJ2735MsgWorker::ConvertJ2735FrameToXML(const MessageFrame_t *messageFrame) + string TelematicBridgeMsgWorker::ConvertJ2735FrameToXML(const MessageFrame_t *messageFrame) { /** * Convert J2735 message into XML @@ -88,7 +88,7 @@ namespace TelematicBridge return string(xml_buffer.buffer); } - int TelematicBridgeJ2735MsgWorker::dynamic_buffer_append(const void *buffer, size_t size, void *app_key) + int TelematicBridgeMsgWorker::dynamic_buffer_append(const void *buffer, size_t size, void *app_key) { auto *xb = static_cast(app_key); @@ -113,4 +113,27 @@ namespace TelematicBridge xb->buffer[xb->buffer_size] = '\0'; return 0; } + + string TelematicBridgeMsgWorker::JsonToString(const Json::Value &json) + { + Json::FastWriter fasterWirter; + string json_str = fasterWirter.write(json); + return json_str; + } + + Json::Value TelematicBridgeMsgWorker::constructTelematicJSONPayload(const IvpMessage *msg) + { + Json::Value json; + json["type"] = msg->type; + json["subType"] = msg->subtype; + json["channel"] = msg->dsrcMetadata->channel; + json["psid"] = msg->dsrcMetadata->psid; + json["encoding"] = msg->encoding; + json["source"] = msg->source; + json["sourceId"] = msg->sourceId; + json["flags"] = msg->flags; + json["timestamp"] = msg->timestamp; + json["payload"] = msg->payload->valuestring; + return json; + } } // TelematicBridge \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h similarity index 72% rename from src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.h rename to src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h index ae439b923..e2d1988b0 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeJ2735MsgWorker.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h @@ -2,6 +2,7 @@ #include "PluginLog.h" #include #include "TelematicBridgeException.h" +#include "jsoncpp/json/json.h" using namespace tmx::utils; using namespace std; @@ -16,7 +17,7 @@ namespace TelematicBridge size_t allocated_size; // this is the total size of the buffer. }; - class TelematicBridgeJ2735MsgWorker + class TelematicBridgeMsgWorker { public: /** @@ -41,8 +42,21 @@ namespace TelematicBridge */ static string ConvertJ2735FrameToXML(const MessageFrame_t *messageframe); static int dynamic_buffer_append(const void *buffer, size_t size, void *app_key); - TelematicBridgeJ2735MsgWorker() = delete; - ~TelematicBridgeJ2735MsgWorker() = delete; + /** + * @brief convert JSON value into string + * @param JSON input Json::Value + * @return string + */ + static string JsonToString(const Json::Value &json); + + /** + * @brief create Telematic payload from given IVP message + * @param IVPMessage V2xHub interval exchanged message + * @return JSON value + */ + static Json::Value constructTelematicJSONPayload(const IvpMessage *msg); + TelematicBridgeMsgWorker() = delete; + ~TelematicBridgeMsgWorker() = delete; }; } // TelematicBridge diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index e30e8eba6..720287504 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -2,7 +2,7 @@ namespace TelematicBridge { - TelematicBridgePlugin::TelematicBridgePlugin(const string& name) : PluginClient(name) + TelematicBridgePlugin::TelematicBridgePlugin(const string &name) : PluginClient(name) { AddMessageFilter("*", "*", IvpMsgFlags_None); SubscribeToMessages(); @@ -10,22 +10,20 @@ namespace TelematicBridge void TelematicBridgePlugin::OnMessageReceived(IvpMessage *msg) { - PLOG(logINFO) << "Message Received." - << " Type: " << msg->type << ", SubType: " << msg->subtype << ", DSRC metadata: " << msg->dsrcMetadata << ", encoding: " << msg->encoding << ", source: " << msg->source << ", sourceId: " << msg->sourceId << ", flags: " << msg->flags << ", timestamp: " << msg->timestamp << ", payload: " << msg->payload->valuestring; + auto json = TelematicBridgeMsgWorker::constructTelematicJSONPayload(msg); // Process J2735 message if (strcasecmp(msg->type, Telematic_MSGTYPE_J2735_STRING) == 0) { auto messageFm = (MessageFrame_t *)malloc(sizeof(MessageFrame_t)); - TelematicBridgeJ2735MsgWorker::DecodeJ2735Msg(msg->payload->valuestring, messageFm); - string xml_payload_str = TelematicBridgeJ2735MsgWorker::ConvertJ2735FrameToXML(messageFm); + TelematicBridgeMsgWorker::DecodeJ2735Msg(msg->payload->valuestring, messageFm); + string xml_payload_str = TelematicBridgeMsgWorker::ConvertJ2735FrameToXML(messageFm); ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFm); string json_payload_str = xml2json(xml_payload_str.c_str()); - PLOG(logINFO) << json_payload_str; - } - else - { - PLOG(logINFO) << msg; + json["payload"] = json_payload_str; } + + auto jsonStr = TelematicBridgeMsgWorker::JsonToString(json); + PLOG(logDEBUG) << "Message Received. " << jsonStr; } } diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h index 2fdf54051..0953ccd90 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h @@ -2,7 +2,7 @@ #define _TelematicBRIDGEPLUGIN_H_ #include "PluginClient.h" -#include "TelematicBridgeJ2735MsgWorker.h" +#include "TelematicBridgeMsgWorker.h" #include "xml2json.h" using namespace tmx::utils; diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicJ2735MsgWorker.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicMsgWorker.cpp similarity index 52% rename from src/v2i-hub/TelematicBridgePlugin/test/test_TelematicJ2735MsgWorker.cpp rename to src/v2i-hub/TelematicBridgePlugin/test/test_TelematicMsgWorker.cpp index 2aa87c209..b7b180c64 100644 --- a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicJ2735MsgWorker.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicMsgWorker.cpp @@ -1,5 +1,5 @@ #include -#include "TelematicBridgeJ2735MsgWorker.h" +#include "TelematicBridgeMsgWorker.h" #include "stdio.h" using namespace TelematicBridge; @@ -13,7 +13,7 @@ TEST_F(test_TelematicJ2735MsgWorker, HexToBytes) { vector byteBuff; string bsmHex = "0014251d59d162dad7de266e9a7d1ea6d4220974ffffffff8ffff080fdfa1fa1007fff0000640fa0"; - auto success = TelematicBridgeJ2735MsgWorker::HexToBytes(bsmHex, byteBuff); + auto success = TelematicBridgeMsgWorker::HexToBytes(bsmHex, byteBuff); ASSERT_TRUE(success); ASSERT_EQ(bsmHex.size() / 2, byteBuff.size()); } @@ -22,7 +22,7 @@ TEST_F(test_TelematicJ2735MsgWorker, DecodeJ2735Msg) { auto messageFrame = (MessageFrame_t *)malloc(sizeof(MessageFrame_t)); string bsmHex = "0014251d59d162dad7de266e9a7d1ea6d4220974ffffffff8ffff080fdfa1fa1007fff0000640fa0"; - ASSERT_NO_THROW(TelematicBridgeJ2735MsgWorker::DecodeJ2735Msg(bsmHex, messageFrame)); + ASSERT_NO_THROW(TelematicBridgeMsgWorker::DecodeJ2735Msg(bsmHex, messageFrame)); ASSERT_EQ(20, messageFrame->messageId); ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFrame); } @@ -31,10 +31,10 @@ TEST_F(test_TelematicJ2735MsgWorker, DecodeJ2735MsgFailure) { auto messageFrame = (MessageFrame_t *)malloc(sizeof(MessageFrame_t)); string badHex = "0014251d59d162dad7de266e9a7d1ea6d4220974ffffffff8ffff080fdfa1fa1007fff0000640fG0"; - ASSERT_THROW(TelematicBridgeJ2735MsgWorker::DecodeJ2735Msg(badHex, messageFrame), TelematicBridgeException); + ASSERT_THROW(TelematicBridgeMsgWorker::DecodeJ2735Msg(badHex, messageFrame), TelematicBridgeException); badHex = "0014251d59d162dad7de266e9a"; - ASSERT_THROW(TelematicBridgeJ2735MsgWorker::DecodeJ2735Msg(badHex, messageFrame), TelematicBridgeException); + ASSERT_THROW(TelematicBridgeMsgWorker::DecodeJ2735Msg(badHex, messageFrame), TelematicBridgeException); ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFrame); } @@ -42,9 +42,43 @@ TEST_F(test_TelematicJ2735MsgWorker, ConvertJ2735FrameToXML) { auto messageFrame = (MessageFrame_t *)malloc(sizeof(MessageFrame_t)); string bsmHex = "0014251d59d162dad7de266e9a7d1ea6d4220974ffffffff8ffff080fdfa1fa1007fff0000640fA0"; - ASSERT_NO_THROW(TelematicBridgeJ2735MsgWorker::DecodeJ2735Msg(bsmHex, messageFrame)); - auto xmlStr = TelematicBridgeJ2735MsgWorker::ConvertJ2735FrameToXML(messageFrame); + ASSERT_NO_THROW(TelematicBridgeMsgWorker::DecodeJ2735Msg(bsmHex, messageFrame)); + auto xmlStr = TelematicBridgeMsgWorker::ConvertJ2735FrameToXML(messageFrame); ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFrame); string expectedXMLStr = "2011767458B6B24440389565434-7715004757452552556553581912880012720012001-127000000200500"; ASSERT_EQ(expectedXMLStr, xmlStr); +} + +TEST_F(test_TelematicJ2735MsgWorker, constructTelematicPayload) +{ + IvpMessage msg; + cJSON *payload = cJSON_CreateObject(); + payload->valuestring = "{\"payload\": \"test\"}"; + msg.payload = payload; + msg.source = "Plugin"; + msg.encoding = "json"; + msg.type = "Application"; + msg.subtype = "alive"; + msg.sourceId = 123; + msg.flags = 10; + msg.timestamp = 10; + IvpDsrcMetadata metadata; + metadata.channel = 12; + metadata.psid = 120; + msg.dsrcMetadata = &metadata; + auto json = TelematicBridgeMsgWorker::constructTelematicJSONPayload(&msg); + ASSERT_EQ("Application", json["type"].asString()); + ASSERT_EQ("alive", json["subType"].asString()); + ASSERT_EQ(12, json["channel"].asInt64()); + ASSERT_EQ("json", json["encoding"].asString()); + ASSERT_EQ("Plugin", json["source"].asString()); + ASSERT_EQ(123, json["sourceId"].asInt64()); + ASSERT_EQ(10, json["flags"].asInt64()); + ASSERT_EQ(10, json["timestamp"].asInt()); + ASSERT_EQ(120, json["psid"].asInt()); + ASSERT_EQ(12, json["channel"].asInt()); + ASSERT_EQ("{\"payload\": \"test\"}", json["payload"].asString()); + auto str = TelematicBridgeMsgWorker::JsonToString(json); + string expectedStr = "{\"channel\":12,\"encoding\":\"json\",\"flags\":10,\"payload\":\"{\\\"payload\\\": \\\"test\\\"}\",\"psid\":120,\"source\":\"Plugin\",\"sourceId\":123,\"subType\":\"alive\",\"timestamp\":10,\"type\":\"Application\"}\n"; + ASSERT_EQ(expectedStr, str); } \ No newline at end of file From 47de4e6a520ba9b7634adb11a8bb206fc89fa407 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 17 Nov 2023 04:19:36 +0000 Subject: [PATCH 08/48] update --- .../src/TelematicBridgeMsgWorker.cpp | 67 ++++++++++++++++--- .../src/TelematicBridgeMsgWorker.h | 16 +++-- .../src/TelematicBridgePlugin.cpp | 29 ++++---- .../test/test_TelematicMsgWorker.cpp | 45 ++++++++----- 4 files changed, 115 insertions(+), 42 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.cpp index dbe826079..c06247a51 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.cpp @@ -117,23 +117,70 @@ namespace TelematicBridge string TelematicBridgeMsgWorker::JsonToString(const Json::Value &json) { Json::FastWriter fasterWirter; - string json_str = fasterWirter.write(json); - return json_str; + string jsonStr = fasterWirter.write(json); + boost::replace_all(jsonStr, "\\n", ""); + boost::replace_all(jsonStr, "\n", ""); + boost::replace_all(jsonStr, "\\t", ""); + boost::replace_all(jsonStr, "\\", ""); + return jsonStr; } - Json::Value TelematicBridgeMsgWorker::constructTelematicJSONPayload(const IvpMessage *msg) + Json::Value TelematicBridgeMsgWorker::StringToJson(const string &str) + { + Json::Value root; + Json::Reader reader; + bool parsingSuccessful = reader.parse(str, root); + if (!parsingSuccessful) + { + throw TelematicBridgeException("Error parsing the string"); + } + return root; + } + + Json::Value TelematicBridgeMsgWorker::ivpMessageToJson(const IvpMessage *msg) { Json::Value json; - json["type"] = msg->type; - json["subType"] = msg->subtype; - json["channel"] = msg->dsrcMetadata->channel; - json["psid"] = msg->dsrcMetadata->psid; - json["encoding"] = msg->encoding; - json["source"] = msg->source; + if (msg->type) + { + json["type"] = msg->type; + } + + if (msg->subtype) + { + json["subType"] = msg->subtype; + } + + if (msg->dsrcMetadata) + { + json["channel"] = msg->dsrcMetadata->channel; + json["psid"] = msg->dsrcMetadata->psid; + } + + if (msg->encoding) + { + json["encoding"] = msg->encoding; + } + + if (msg->source) + { + json["source"] = msg->source; + } json["sourceId"] = msg->sourceId; json["flags"] = msg->flags; json["timestamp"] = msg->timestamp; - json["payload"] = msg->payload->valuestring; + if (msg->payload) + { + switch (msg->payload->type) + { + case cJSON_Number: + json["payload"] = (msg->payload->valueint == 0 ? msg->payload->valuedouble : msg->payload->valueint); + break; + default: + json["payload"] = StringToJson(cJSON_Print(msg->payload)); + break; + } + } + return json; } } // TelematicBridge \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h index e2d1988b0..3aab5b78c 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h @@ -3,6 +3,7 @@ #include #include "TelematicBridgeException.h" #include "jsoncpp/json/json.h" +#include using namespace tmx::utils; using namespace std; @@ -46,15 +47,20 @@ namespace TelematicBridge * @brief convert JSON value into string * @param JSON input Json::Value * @return string - */ + */ static string JsonToString(const Json::Value &json); - + /** + * @brief convert string into JSON value + * @param string input string + * @return JSON::Value + */ + static Json::Value StringToJson(const string &str); /** - * @brief create Telematic payload from given IVP message + * @brief create JSON payload from given IVP message * @param IVPMessage V2xHub interval exchanged message * @return JSON value - */ - static Json::Value constructTelematicJSONPayload(const IvpMessage *msg); + */ + static Json::Value ivpMessageToJson(const IvpMessage *msg); TelematicBridgeMsgWorker() = delete; ~TelematicBridgeMsgWorker() = delete; }; diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index 720287504..2dcff42fb 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -10,20 +10,25 @@ namespace TelematicBridge void TelematicBridgePlugin::OnMessageReceived(IvpMessage *msg) { - auto json = TelematicBridgeMsgWorker::constructTelematicJSONPayload(msg); - // Process J2735 message - if (strcasecmp(msg->type, Telematic_MSGTYPE_J2735_STRING) == 0) + if (msg && msg->type) { - auto messageFm = (MessageFrame_t *)malloc(sizeof(MessageFrame_t)); - TelematicBridgeMsgWorker::DecodeJ2735Msg(msg->payload->valuestring, messageFm); - string xml_payload_str = TelematicBridgeMsgWorker::ConvertJ2735FrameToXML(messageFm); - ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFm); - string json_payload_str = xml2json(xml_payload_str.c_str()); - json["payload"] = json_payload_str; - } + PLOG(logDEBUG2) << "Message Received." + << " Type: " << msg->type << ", SubType: " << msg->subtype << ", DSRC metadata: " << msg->dsrcMetadata << ", encoding: " << msg->encoding << ", source: " << msg->source << ", sourceId: " << msg->sourceId << ", flags: " << msg->flags << ", timestamp: " << msg->timestamp << ", payload: " << cJSON_Print(msg->payload); + auto json = TelematicBridgeMsgWorker::ivpMessageToJson(msg); + // Process J2735 message payload hex string + if (strcasecmp(msg->type, Telematic_MSGTYPE_J2735_STRING) == 0) + { + auto messageFm = (MessageFrame_t *)malloc(sizeof(MessageFrame_t)); + TelematicBridgeMsgWorker::DecodeJ2735Msg(msg->payload->valuestring, messageFm); + string xml_payload_str = TelematicBridgeMsgWorker::ConvertJ2735FrameToXML(messageFm); + ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFm); + string json_payload_str = xml2json(xml_payload_str.c_str()); + json["payload"] = TelematicBridgeMsgWorker::StringToJson(json_payload_str); + } - auto jsonStr = TelematicBridgeMsgWorker::JsonToString(json); - PLOG(logDEBUG) << "Message Received. " << jsonStr; + auto jsonStr = TelematicBridgeMsgWorker::JsonToString(json); + PLOG(logINFO) << jsonStr; + } } } diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicMsgWorker.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicMsgWorker.cpp index b7b180c64..d2a5198c2 100644 --- a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicMsgWorker.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicMsgWorker.cpp @@ -52,8 +52,9 @@ TEST_F(test_TelematicJ2735MsgWorker, ConvertJ2735FrameToXML) TEST_F(test_TelematicJ2735MsgWorker, constructTelematicPayload) { IvpMessage msg; - cJSON *payload = cJSON_CreateObject(); - payload->valuestring = "{\"payload\": \"test\"}"; + auto payload = cJSON_CreateObject(); + payload->valuedouble = 12; + payload->type = cJSON_Number; msg.payload = payload; msg.source = "Plugin"; msg.encoding = "json"; @@ -66,19 +67,33 @@ TEST_F(test_TelematicJ2735MsgWorker, constructTelematicPayload) metadata.channel = 12; metadata.psid = 120; msg.dsrcMetadata = &metadata; - auto json = TelematicBridgeMsgWorker::constructTelematicJSONPayload(&msg); - ASSERT_EQ("Application", json["type"].asString()); - ASSERT_EQ("alive", json["subType"].asString()); - ASSERT_EQ(12, json["channel"].asInt64()); - ASSERT_EQ("json", json["encoding"].asString()); - ASSERT_EQ("Plugin", json["source"].asString()); - ASSERT_EQ(123, json["sourceId"].asInt64()); - ASSERT_EQ(10, json["flags"].asInt64()); - ASSERT_EQ(10, json["timestamp"].asInt()); - ASSERT_EQ(120, json["psid"].asInt()); - ASSERT_EQ(12, json["channel"].asInt()); - ASSERT_EQ("{\"payload\": \"test\"}", json["payload"].asString()); + auto json = TelematicBridgeMsgWorker::ivpMessageToJson(&msg); auto str = TelematicBridgeMsgWorker::JsonToString(json); - string expectedStr = "{\"channel\":12,\"encoding\":\"json\",\"flags\":10,\"payload\":\"{\\\"payload\\\": \\\"test\\\"}\",\"psid\":120,\"source\":\"Plugin\",\"sourceId\":123,\"subType\":\"alive\",\"timestamp\":10,\"type\":\"Application\"}\n"; + string expectedStr = "{\"channel\":12,\"encoding\":\"json\",\"flags\":10,\"payload\":12.0,\"psid\":120,\"source\":\"Plugin\",\"sourceId\":123,\"subType\":\"alive\",\"timestamp\":10,\"type\":\"Application\"}"; ASSERT_EQ(expectedStr, str); + + payload->valueint = 13; + payload->type = cJSON_Number; + msg.payload = payload; + json = TelematicBridgeMsgWorker::ivpMessageToJson(&msg); + str = TelematicBridgeMsgWorker::JsonToString(json); + expectedStr = "{\"channel\":12,\"encoding\":\"json\",\"flags\":10,\"payload\":13.0,\"psid\":120,\"source\":\"Plugin\",\"sourceId\":123,\"subType\":\"alive\",\"timestamp\":10,\"type\":\"Application\"}"; + ASSERT_EQ(expectedStr, str); + + payload->valuestring = "test"; + payload->type = cJSON_String; + msg.payload = payload; + json = TelematicBridgeMsgWorker::ivpMessageToJson(&msg); + str = TelematicBridgeMsgWorker::JsonToString(json); + expectedStr = "{\"channel\":12,\"encoding\":\"json\",\"flags\":10,\"payload\":\"test\",\"psid\":120,\"source\":\"Plugin\",\"sourceId\":123,\"subType\":\"alive\",\"timestamp\":10,\"type\":\"Application\"}"; + ASSERT_EQ(expectedStr, str); + + msg.payload = cJSON_Parse("[{\"test\":12}]"); + json = TelematicBridgeMsgWorker::ivpMessageToJson(&msg); + str = TelematicBridgeMsgWorker::JsonToString(json); + expectedStr = "{\"channel\":12,\"encoding\":\"json\",\"flags\":10,\"payload\":[{\"test\":12}],\"psid\":120,\"source\":\"Plugin\",\"sourceId\":123,\"subType\":\"alive\",\"timestamp\":10,\"type\":\"Application\"}"; + ASSERT_EQ(expectedStr, str); + + json = TelematicBridgeMsgWorker::StringToJson("{\"test\":12}"); + ASSERT_EQ(12,json["test"].asInt64()); } \ No newline at end of file From 30d8528cdd0219ec237ece52bf49cf757d5f81f5 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 17 Nov 2023 04:22:12 +0000 Subject: [PATCH 09/48] update --- .../src/TelematicBridgeMsgWorker.cpp | 6 +++--- .../TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h | 4 ++-- .../TelematicBridgePlugin/src/TelematicBridgePlugin.cpp | 2 +- .../test/test_TelematicMsgWorker.cpp | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.cpp index c06247a51..687093345 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.cpp @@ -79,7 +79,7 @@ namespace TelematicBridge &asn_DEF_MessageFrame, messageFrame, XER_F_CANONICAL, - dynamic_buffer_append, + DynamicBufferAppend, static_cast(&xml_buffer)); if (encode_rval.encoded == -1) { @@ -88,7 +88,7 @@ namespace TelematicBridge return string(xml_buffer.buffer); } - int TelematicBridgeMsgWorker::dynamic_buffer_append(const void *buffer, size_t size, void *app_key) + int TelematicBridgeMsgWorker::DynamicBufferAppend(const void *buffer, size_t size, void *app_key) { auto *xb = static_cast(app_key); @@ -137,7 +137,7 @@ namespace TelematicBridge return root; } - Json::Value TelematicBridgeMsgWorker::ivpMessageToJson(const IvpMessage *msg) + Json::Value TelematicBridgeMsgWorker::IvpMessageToJson(const IvpMessage *msg) { Json::Value json; if (msg->type) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h index 3aab5b78c..db616a254 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h @@ -42,7 +42,7 @@ namespace TelematicBridge * @return string XML formatted J2735 message */ static string ConvertJ2735FrameToXML(const MessageFrame_t *messageframe); - static int dynamic_buffer_append(const void *buffer, size_t size, void *app_key); + static int DynamicBufferAppend(const void *buffer, size_t size, void *app_key); /** * @brief convert JSON value into string * @param JSON input Json::Value @@ -60,7 +60,7 @@ namespace TelematicBridge * @param IVPMessage V2xHub interval exchanged message * @return JSON value */ - static Json::Value ivpMessageToJson(const IvpMessage *msg); + static Json::Value IvpMessageToJson(const IvpMessage *msg); TelematicBridgeMsgWorker() = delete; ~TelematicBridgeMsgWorker() = delete; }; diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index 2dcff42fb..372e5ae32 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -14,7 +14,7 @@ namespace TelematicBridge { PLOG(logDEBUG2) << "Message Received." << " Type: " << msg->type << ", SubType: " << msg->subtype << ", DSRC metadata: " << msg->dsrcMetadata << ", encoding: " << msg->encoding << ", source: " << msg->source << ", sourceId: " << msg->sourceId << ", flags: " << msg->flags << ", timestamp: " << msg->timestamp << ", payload: " << cJSON_Print(msg->payload); - auto json = TelematicBridgeMsgWorker::ivpMessageToJson(msg); + auto json = TelematicBridgeMsgWorker::IvpMessageToJson(msg); // Process J2735 message payload hex string if (strcasecmp(msg->type, Telematic_MSGTYPE_J2735_STRING) == 0) { diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicMsgWorker.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicMsgWorker.cpp index d2a5198c2..ac9494e64 100644 --- a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicMsgWorker.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicMsgWorker.cpp @@ -67,7 +67,7 @@ TEST_F(test_TelematicJ2735MsgWorker, constructTelematicPayload) metadata.channel = 12; metadata.psid = 120; msg.dsrcMetadata = &metadata; - auto json = TelematicBridgeMsgWorker::ivpMessageToJson(&msg); + auto json = TelematicBridgeMsgWorker::IvpMessageToJson(&msg); auto str = TelematicBridgeMsgWorker::JsonToString(json); string expectedStr = "{\"channel\":12,\"encoding\":\"json\",\"flags\":10,\"payload\":12.0,\"psid\":120,\"source\":\"Plugin\",\"sourceId\":123,\"subType\":\"alive\",\"timestamp\":10,\"type\":\"Application\"}"; ASSERT_EQ(expectedStr, str); @@ -75,7 +75,7 @@ TEST_F(test_TelematicJ2735MsgWorker, constructTelematicPayload) payload->valueint = 13; payload->type = cJSON_Number; msg.payload = payload; - json = TelematicBridgeMsgWorker::ivpMessageToJson(&msg); + json = TelematicBridgeMsgWorker::IvpMessageToJson(&msg); str = TelematicBridgeMsgWorker::JsonToString(json); expectedStr = "{\"channel\":12,\"encoding\":\"json\",\"flags\":10,\"payload\":13.0,\"psid\":120,\"source\":\"Plugin\",\"sourceId\":123,\"subType\":\"alive\",\"timestamp\":10,\"type\":\"Application\"}"; ASSERT_EQ(expectedStr, str); @@ -83,13 +83,13 @@ TEST_F(test_TelematicJ2735MsgWorker, constructTelematicPayload) payload->valuestring = "test"; payload->type = cJSON_String; msg.payload = payload; - json = TelematicBridgeMsgWorker::ivpMessageToJson(&msg); + json = TelematicBridgeMsgWorker::IvpMessageToJson(&msg); str = TelematicBridgeMsgWorker::JsonToString(json); expectedStr = "{\"channel\":12,\"encoding\":\"json\",\"flags\":10,\"payload\":\"test\",\"psid\":120,\"source\":\"Plugin\",\"sourceId\":123,\"subType\":\"alive\",\"timestamp\":10,\"type\":\"Application\"}"; ASSERT_EQ(expectedStr, str); msg.payload = cJSON_Parse("[{\"test\":12}]"); - json = TelematicBridgeMsgWorker::ivpMessageToJson(&msg); + json = TelematicBridgeMsgWorker::IvpMessageToJson(&msg); str = TelematicBridgeMsgWorker::JsonToString(json); expectedStr = "{\"channel\":12,\"encoding\":\"json\",\"flags\":10,\"payload\":[{\"test\":12}],\"psid\":120,\"source\":\"Plugin\",\"sourceId\":123,\"subType\":\"alive\",\"timestamp\":10,\"type\":\"Application\"}"; ASSERT_EQ(expectedStr, str); From eece9af71430773f4417cebf5c9d8753c901635e Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 17 Nov 2023 14:45:39 +0000 Subject: [PATCH 10/48] flat json --- .../RSUHealthMonitorPlugin/src/RSUHealthMonitorWorker.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/v2i-hub/RSUHealthMonitorPlugin/src/RSUHealthMonitorWorker.cpp b/src/v2i-hub/RSUHealthMonitorPlugin/src/RSUHealthMonitorWorker.cpp index 6de25d57e..6ac62f9fc 100644 --- a/src/v2i-hub/RSUHealthMonitorPlugin/src/RSUHealthMonitorWorker.cpp +++ b/src/v2i-hub/RSUHealthMonitorPlugin/src/RSUHealthMonitorWorker.cpp @@ -145,7 +145,11 @@ namespace RSUHealthMonitor } else if (success) { - rsuStatuJson.append(populateJson(config.field, responseVal)); + auto json = populateJson(config.field, responseVal); + for(const auto &key: json.getMemberNames()) + { + rsuStatuJson[key] = json[key]; + } } } } From b9d209e189500d7edc46f9401369c2456bb2917f Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 17 Nov 2023 14:48:13 +0000 Subject: [PATCH 11/48] update unit test --- .../test/test_RSUHealthMonitorWorker.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/v2i-hub/RSUHealthMonitorPlugin/test/test_RSUHealthMonitorWorker.cpp b/src/v2i-hub/RSUHealthMonitorPlugin/test/test_RSUHealthMonitorWorker.cpp index 9d749f0df..cc61247b5 100644 --- a/src/v2i-hub/RSUHealthMonitorPlugin/test/test_RSUHealthMonitorWorker.cpp +++ b/src/v2i-hub/RSUHealthMonitorPlugin/test/test_RSUHealthMonitorWorker.cpp @@ -87,7 +87,10 @@ namespace RSUHealthMonitor double expected_longitude = -77.1496; ASSERT_NEAR(expected_latitude, json["rsuGpsOutputStringLatitude"].asDouble(), 0.001); ASSERT_NEAR(expected_longitude, json["rsuGpsOutputStringLongitude"].asDouble(), 0.001); - rsuStatusJson.append(json); + for(const auto& key: json.getMemberNames()) + { + rsuStatusJson[key] = json[key]; + } snmp_response_obj intObj; intObj.type = snmp_response_obj::response_type::INTEGER; @@ -95,11 +98,11 @@ namespace RSUHealthMonitor json = _rsuWorker->populateJson("rsuMode", intObj); ASSERT_EQ(4, json["rsuMode"].asInt64()); - rsuStatusJson.append(json); + rsuStatusJson["rsuMode"] = json["rsuMode"]; Json::FastWriter fasterWirter; string json_str = fasterWirter.write(rsuStatusJson); - string expectedStr = "[{\"rsuGpsOutputString\":\"$GPGGA,142440.00,3857.3065,N,07708.9734,W,2,18,0.65,86.18,M,-34.722,M,,*62\",\"rsuGpsOutputStringLatitude\":38.955108330000002,\"rsuGpsOutputStringLongitude\":-77.149556669999996},{\"rsuMode\":4}]\n"; + string expectedStr = "{\"rsuGpsOutputString\":\"$GPGGA,142440.00,3857.3065,N,07708.9734,W,2,18,0.65,86.18,M,-34.722,M,,*62\",\"rsuGpsOutputStringLatitude\":38.955108330000002,\"rsuGpsOutputStringLongitude\":-77.149556669999996,\"rsuMode\":4}\n"; ASSERT_EQ(expectedStr, json_str); ASSERT_EQ(4, _rsuWorker->getJsonKeys(rsuStatusJson).size()); ASSERT_EQ(1, _rsuWorker->getJsonKeys(json).size()); From 8b4d24d116b84bc9d2fc634f059844f8a56ea4a8 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 17 Nov 2023 16:03:33 +0000 Subject: [PATCH 12/48] code smell --- .../src/TelematicBridgeMsgWorker.cpp | 12 +++++------- src/v2i-hub/TelematicBridgePlugin/src/xml2json.h | 16 +++++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.cpp index 687093345..e418df767 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.cpp @@ -48,7 +48,6 @@ namespace TelematicBridge */ ostringstream erroross; vector byte_buffer; - static constexpr size_t max_errbuf_size = 128; if (!HexToBytes(hexPaylod, byte_buffer)) { throw TelematicBridgeException("Failed attempt to decode MessageFrame hex string: cannot convert to bytes."); @@ -170,14 +169,13 @@ namespace TelematicBridge json["timestamp"] = msg->timestamp; if (msg->payload) { - switch (msg->payload->type) + if (msg->payload->type == cJSON_Number) + { + json["payload"] = (msg->payload->valueint == 0 ? msg->payload->valuedouble : static_cast(msg->payload->valueint)); + } + else { - case cJSON_Number: - json["payload"] = (msg->payload->valueint == 0 ? msg->payload->valuedouble : msg->payload->valueint); - break; - default: json["payload"] = StringToJson(cJSON_Print(msg->payload)); - break; } } diff --git a/src/v2i-hub/TelematicBridgePlugin/src/xml2json.h b/src/v2i-hub/TelematicBridgePlugin/src/xml2json.h index 9883b16b2..c22a3053d 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/xml2json.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/xml2json.h @@ -93,7 +93,8 @@ void xml2json_add_attributes(const rapidxml::xml_node<> *xmlnode, rapidjson::Val { for (auto myattr = xmlnode->first_attribute(); myattr; myattr = myattr->next_attribute()) { - rapidjson::Value jn, jv; + rapidjson::Value jn; + rapidjson::Value jv; jn.SetString((std::string(xml2json_attribute_name_prefix) + myattr->name()).c_str(), allocator); if (xml2json_numeric_support == false) @@ -131,7 +132,6 @@ void xml2json_traverse_node(rapidxml::xml_node<> *xmlnode, rapidjson::Value &jsv jsvalue.SetObject(); jsvalue_chd.SetObject(); - rapidxml::xml_node<> *xmlnode_chd; // classified discussion: if ((xmlnode->type() == rapidxml::node_data || xmlnode->type() == rapidxml::node_cdata) && xmlnode->value()) @@ -146,7 +146,8 @@ void xml2json_traverse_node(rapidxml::xml_node<> *xmlnode, rapidjson::Value &jsv if (xmlnode->first_node() && xmlnode->first_node()->type() == rapidxml::node_data && count_children(xmlnode) == 1) { // case: text - rapidjson::Value jn, jv; + rapidjson::Value jn; + rapidjson::Value jv; jn.SetString(xml2json_text_additional_name, allocator); jv.SetString(xmlnode->first_node()->value(), allocator); jsvalue.AddMember(jn, jv, allocator); @@ -191,7 +192,7 @@ void xml2json_traverse_node(rapidxml::xml_node<> *xmlnode, rapidjson::Value &jsv else { long int value = std::strtol(xmlnode->first_node()->value(), nullptr, 0); - jsvalue.SetInt(value); + jsvalue.SetInt(static_cast(value)); } } } @@ -202,11 +203,12 @@ void xml2json_traverse_node(rapidxml::xml_node<> *xmlnode, rapidjson::Value &jsv { // case: complex else... std::map name_count; - for (xmlnode_chd = xmlnode->first_node(); xmlnode_chd; xmlnode_chd = xmlnode_chd->next_sibling()) + for (auto xmlnode_chd = xmlnode->first_node(); xmlnode_chd; xmlnode_chd = xmlnode_chd->next_sibling()) { std::string current_name; - const char *name_ptr = NULL; - rapidjson::Value jn, jv; + const char *name_ptr = nullptr; + rapidjson::Value jn; + rapidjson::Value jv; if (xmlnode_chd->type() == rapidxml::node_data || xmlnode_chd->type() == rapidxml::node_cdata) { current_name = xml2json_text_additional_name; From 5ca81e0164304caaa46367ebb61763ded5c7607b Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 20 Nov 2023 15:09:28 +0000 Subject: [PATCH 13/48] address comments --- .../TelematicBridgePlugin/CMakeLists.txt | 6 +- .../src/TelematicBridgeMsgWorker.cpp | 184 ------------- .../src/TelematicBridgeMsgWorker.h | 244 +++++++++++++++--- .../src/TelematicBridgePlugin.cpp | 11 +- .../test/test_TelematicMsgWorker.cpp | 30 +-- 5 files changed, 225 insertions(+), 250 deletions(-) delete mode 100644 src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.cpp diff --git a/src/v2i-hub/TelematicBridgePlugin/CMakeLists.txt b/src/v2i-hub/TelematicBridgePlugin/CMakeLists.txt index 5f25fc4bc..5134ae38b 100644 --- a/src/v2i-hub/TelematicBridgePlugin/CMakeLists.txt +++ b/src/v2i-hub/TelematicBridgePlugin/CMakeLists.txt @@ -2,8 +2,6 @@ PROJECT (TelematicBridgePlugin VERSION 7.5.1 LANGUAGES CXX) set (TMX_PLUGIN_NAME "Telematic Bridge") -find_package(RapidJSON REQUIRED) - BuildTmxPlugin() TARGET_LINK_LIBRARIES ( ${PROJECT_NAME} tmxutils jsoncpp) @@ -12,8 +10,6 @@ TARGET_LINK_LIBRARIES ( ${PROJECT_NAME} tmxutils jsoncpp) #################################################### enable_testing() include_directories(${PROJECT_SOURCE_DIR}/src) -add_library(${PROJECT_NAME}_lib src/TelematicBridgeMsgWorker.cpp) -target_link_libraries(${PROJECT_NAME}_lib PUBLIC tmxutils jsoncpp) file(GLOB_RECURSE TEST_SOURCES LIST_DIRECTORIES false test/*.h test/*.cpp) add_executable(${PROJECT_NAME}_test ${TEST_SOURCES}) -target_link_libraries(${PROJECT_NAME}_test PRIVATE ${PROJECT_NAME}_lib gtest) \ No newline at end of file +target_link_libraries(${PROJECT_NAME}_test PRIVATE gtest tmxutils jsoncpp) \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.cpp deleted file mode 100644 index e418df767..000000000 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.cpp +++ /dev/null @@ -1,184 +0,0 @@ -#include "TelematicBridgeMsgWorker.h" - -namespace TelematicBridge -{ - bool TelematicBridgeMsgWorker::HexToBytes(const string &hexPaylod, vector &byteBuffer) - { - uint8_t d = 0; - int i = 0; - - for (const char &c : hexPaylod) - { - if (c <= '9' && c >= '0') - { - d = c - '0'; - } - else if (c <= 'F' && c >= 'A') - { - d = c - 55; // c - 'A' + 10 - } - else if (c <= 'f' && c >= 'a') - { - d = c - 87; // c - 'a' + 10; - } - else - { - return false; - } - - if (i % 2) - { - // low order nibble. - byteBuffer.back() |= d; - } - else - { - // high order nibble. - byteBuffer.push_back(d << 4); - } - ++i; - } - return true; - } - - void TelematicBridgeMsgWorker::DecodeJ2735Msg(const string &hexPaylod, MessageFrame_t *messageFrame) - { - /** - * Decode J2735 message - */ - ostringstream erroross; - vector byte_buffer; - if (!HexToBytes(hexPaylod, byte_buffer)) - { - throw TelematicBridgeException("Failed attempt to decode MessageFrame hex string: cannot convert to bytes."); - } - asn_dec_rval_t decode_rval = asn_decode( - nullptr, - ATS_UNALIGNED_BASIC_PER, - &asn_DEF_MessageFrame, - (void **)&messageFrame, - byte_buffer.data(), - byte_buffer.size()); - - if (decode_rval.code != RC_OK) - { - erroross.str(""); - erroross << "failed ASN.1 binary decoding of element " << asn_DEF_MessageFrame.name << ": bad data. Successfully decoded " << decode_rval.consumed << " bytes."; - throw TelematicBridgeException(erroross.str()); - } - } - - string TelematicBridgeMsgWorker::ConvertJ2735FrameToXML(const MessageFrame_t *messageFrame) - { - /** - * Convert J2735 message into XML - */ - buffer_structure_t xml_buffer = {nullptr, 0, 0}; - asn_enc_rval_t encode_rval = xer_encode( - &asn_DEF_MessageFrame, - messageFrame, - XER_F_CANONICAL, - DynamicBufferAppend, - static_cast(&xml_buffer)); - if (encode_rval.encoded == -1) - { - throw TelematicBridgeException("Failed to convert message with ID (=" + to_string(messageFrame->messageId) + ") to XML "); - } - return string(xml_buffer.buffer); - } - - int TelematicBridgeMsgWorker::DynamicBufferAppend(const void *buffer, size_t size, void *app_key) - { - auto *xb = static_cast(app_key); - - while (xb->buffer_size + size + 1 > xb->allocated_size) - { - // increase size of buffer. - size_t new_size = 2 * (xb->allocated_size ? xb->allocated_size : 64); - auto new_buf = static_cast(MALLOC(new_size)); - if (!new_buf) - return -1; - // move old to new. - memcpy(new_buf, xb->buffer, xb->buffer_size); - - FREEMEM(xb->buffer); - xb->buffer = new_buf; - xb->allocated_size = new_size; - } - - memcpy(xb->buffer + xb->buffer_size, buffer, size); - xb->buffer_size += size; - // null terminate the string. - xb->buffer[xb->buffer_size] = '\0'; - return 0; - } - - string TelematicBridgeMsgWorker::JsonToString(const Json::Value &json) - { - Json::FastWriter fasterWirter; - string jsonStr = fasterWirter.write(json); - boost::replace_all(jsonStr, "\\n", ""); - boost::replace_all(jsonStr, "\n", ""); - boost::replace_all(jsonStr, "\\t", ""); - boost::replace_all(jsonStr, "\\", ""); - return jsonStr; - } - - Json::Value TelematicBridgeMsgWorker::StringToJson(const string &str) - { - Json::Value root; - Json::Reader reader; - bool parsingSuccessful = reader.parse(str, root); - if (!parsingSuccessful) - { - throw TelematicBridgeException("Error parsing the string"); - } - return root; - } - - Json::Value TelematicBridgeMsgWorker::IvpMessageToJson(const IvpMessage *msg) - { - Json::Value json; - if (msg->type) - { - json["type"] = msg->type; - } - - if (msg->subtype) - { - json["subType"] = msg->subtype; - } - - if (msg->dsrcMetadata) - { - json["channel"] = msg->dsrcMetadata->channel; - json["psid"] = msg->dsrcMetadata->psid; - } - - if (msg->encoding) - { - json["encoding"] = msg->encoding; - } - - if (msg->source) - { - json["source"] = msg->source; - } - json["sourceId"] = msg->sourceId; - json["flags"] = msg->flags; - json["timestamp"] = msg->timestamp; - if (msg->payload) - { - if (msg->payload->type == cJSON_Number) - { - json["payload"] = (msg->payload->valueint == 0 ? msg->payload->valuedouble : static_cast(msg->payload->valueint)); - } - else - { - json["payload"] = StringToJson(cJSON_Print(msg->payload)); - } - } - - return json; - } -} // TelematicBridge \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h index db616a254..551d171a4 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h @@ -18,51 +18,213 @@ namespace TelematicBridge size_t allocated_size; // this is the total size of the buffer. }; - class TelematicBridgeMsgWorker + /** + * @brief Convert hex string into a vector of bytes + * @param string input hex string payload + * @param vector byte buffer to be updated. + * @return bool indicator whether conversion is successful. + */ + bool HexToBytes(const string &hexPaylod, vector &byteBuffer) { - public: - /** - * @brief Convert hex string into a vector of bytes - * @param string input hex string payload - * @param vector byte buffer to be updated. - * @return bool indicator whether conversion is successful. - */ - static bool HexToBytes(const string &hexPaylod, vector &byteBuffer); + uint8_t d = 0; + int i = 0; + for (const char &c : hexPaylod) + { + if (c <= '9' && c >= '0') + { + d = c - '0'; + } + else if (c <= 'F' && c >= 'A') + { + d = c - 55; // c - 'A' + 10 + } + else if (c <= 'f' && c >= 'a') + { + d = c - 87; // c - 'a' + 10; + } + else + { + return false; + } + + if (i % 2) + { + // low order nibble. + byteBuffer.back() |= d; + } + else + { + // high order nibble. + byteBuffer.push_back(d << 4); + } + ++i; + } + return true; + } + + /** + * @brief Decode J2735 message and populate the J2735 data frame + * @param string input hex string payload + * @param MessageFrame_t J2735 struct to be updated + * @return bool indicator whether decoding successful + */ + void DecodeJ2735Msg(const string &hexPaylod, MessageFrame_t *messageFrame) + { /** - * @brief Decode J2735 message and populate the J2735 data frame - * @param string input hex string payload - * @param MessageFrame_t J2735 struct to be updated - * @return bool indicator whether decoding successful - */ - static void DecodeJ2735Msg(const string &hexPaylod, MessageFrame_t *messageframe); - /** - * @brief Convert the J2735 messageFrame into string in XML format - * @param MessageFrame_t J2735 struct - * @return string XML formatted J2735 message - */ - static string ConvertJ2735FrameToXML(const MessageFrame_t *messageframe); - static int DynamicBufferAppend(const void *buffer, size_t size, void *app_key); - /** - * @brief convert JSON value into string - * @param JSON input Json::Value - * @return string + * Decode J2735 message */ - static string JsonToString(const Json::Value &json); - /** - * @brief convert string into JSON value - * @param string input string - * @return JSON::Value - */ - static Json::Value StringToJson(const string &str); + ostringstream erroross; + vector byte_buffer; + if (!HexToBytes(hexPaylod, byte_buffer)) + { + throw TelematicBridgeException("Failed attempt to decode MessageFrame hex string: cannot convert to bytes."); + } + asn_dec_rval_t decode_rval = asn_decode( + nullptr, + ATS_UNALIGNED_BASIC_PER, + &asn_DEF_MessageFrame, + (void **)&messageFrame, + byte_buffer.data(), + byte_buffer.size()); + + if (decode_rval.code != RC_OK) + { + erroross.str(""); + erroross << "failed ASN.1 binary decoding of element " << asn_DEF_MessageFrame.name << ": bad data. Successfully decoded " << decode_rval.consumed << " bytes."; + throw TelematicBridgeException(erroross.str()); + } + } + + int DynamicBufferAppend(const void *buffer, size_t size, void *app_key) + { + auto *xb = static_cast(app_key); + + while (xb->buffer_size + size + 1 > xb->allocated_size) + { + // increase size of buffer. + size_t new_size = 2 * (xb->allocated_size ? xb->allocated_size : 64); + auto new_buf = static_cast(MALLOC(new_size)); + if (!new_buf) + return -1; + // move old to new. + memcpy(new_buf, xb->buffer, xb->buffer_size); + + FREEMEM(xb->buffer); + xb->buffer = new_buf; + xb->allocated_size = new_size; + } + + memcpy(xb->buffer + xb->buffer_size, buffer, size); + xb->buffer_size += size; + // null terminate the string. + xb->buffer[xb->buffer_size] = '\0'; + return 0; + } + + /** + * @brief Convert the J2735 messageFrame into string in XML format + * @param MessageFrame_t J2735 struct + * @return string XML formatted J2735 message + */ + string ConvertJ2735FrameToXML(const MessageFrame_t *messageFrame) + { /** - * @brief create JSON payload from given IVP message - * @param IVPMessage V2xHub interval exchanged message - * @return JSON value + * Convert J2735 message into XML */ - static Json::Value IvpMessageToJson(const IvpMessage *msg); - TelematicBridgeMsgWorker() = delete; - ~TelematicBridgeMsgWorker() = delete; - }; + buffer_structure_t xml_buffer = {nullptr, 0, 0}; + asn_enc_rval_t encode_rval = xer_encode( + &asn_DEF_MessageFrame, + messageFrame, + XER_F_CANONICAL, + DynamicBufferAppend, + static_cast(&xml_buffer)); + if (encode_rval.encoded == -1) + { + throw TelematicBridgeException("Failed to convert message with ID (=" + to_string(messageFrame->messageId) + ") to XML "); + } + return string(xml_buffer.buffer); + } + + /** + * @brief convert JSON value into string + * @param JSON input Json::Value + * @return string + */ + string JsonToString(const Json::Value &json) + { + Json::FastWriter fasterWirter; + string jsonStr = fasterWirter.write(json); + boost::replace_all(jsonStr, "\\n", ""); + boost::replace_all(jsonStr, "\n", ""); + boost::replace_all(jsonStr, "\\t", ""); + boost::replace_all(jsonStr, "\\", ""); + return jsonStr; + } + /** + * @brief convert string into JSON value + * @param string input string + * @return JSON::Value + */ + Json::Value StringToJson(const string &str) + { + Json::Value root; + Json::Reader reader; + bool parsingSuccessful = reader.parse(str, root); + if (!parsingSuccessful) + { + throw TelematicBridgeException("Error parsing the string"); + } + return root; + } + /** + * @brief create JSON payload from given IVP message + * @param IVPMessage V2xHub interval exchanged message + * @return JSON value + */ + Json::Value IvpMessageToJson(const IvpMessage *msg) + { + Json::Value json; + if (msg->type) + { + json["type"] = msg->type; + } + + if (msg->subtype) + { + json["subType"] = msg->subtype; + } + + if (msg->dsrcMetadata) + { + json["channel"] = msg->dsrcMetadata->channel; + json["psid"] = msg->dsrcMetadata->psid; + } + + if (msg->encoding) + { + json["encoding"] = msg->encoding; + } + + if (msg->source) + { + json["source"] = msg->source; + } + json["sourceId"] = msg->sourceId; + json["flags"] = msg->flags; + json["timestamp"] = msg->timestamp; + if (msg->payload) + { + if (msg->payload->type == cJSON_Number) + { + json["payload"] = (msg->payload->valueint == 0 ? msg->payload->valuedouble : static_cast(msg->payload->valueint)); + } + else + { + json["payload"] = StringToJson(cJSON_Print(msg->payload)); + } + } -} // TelematicBridge + return json; + } +} // TelematicBridge \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index 372e5ae32..4dcd75828 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -5,6 +5,7 @@ namespace TelematicBridge TelematicBridgePlugin::TelematicBridgePlugin(const string &name) : PluginClient(name) { AddMessageFilter("*", "*", IvpMsgFlags_None); + AddMessageFilter("J2735", "*", IvpMsgFlags_RouteDSRC); SubscribeToMessages(); } @@ -14,19 +15,19 @@ namespace TelematicBridge { PLOG(logDEBUG2) << "Message Received." << " Type: " << msg->type << ", SubType: " << msg->subtype << ", DSRC metadata: " << msg->dsrcMetadata << ", encoding: " << msg->encoding << ", source: " << msg->source << ", sourceId: " << msg->sourceId << ", flags: " << msg->flags << ", timestamp: " << msg->timestamp << ", payload: " << cJSON_Print(msg->payload); - auto json = TelematicBridgeMsgWorker::IvpMessageToJson(msg); + auto json = IvpMessageToJson(msg); // Process J2735 message payload hex string if (strcasecmp(msg->type, Telematic_MSGTYPE_J2735_STRING) == 0) { auto messageFm = (MessageFrame_t *)malloc(sizeof(MessageFrame_t)); - TelematicBridgeMsgWorker::DecodeJ2735Msg(msg->payload->valuestring, messageFm); - string xml_payload_str = TelematicBridgeMsgWorker::ConvertJ2735FrameToXML(messageFm); + DecodeJ2735Msg(msg->payload->valuestring, messageFm); + string xml_payload_str = ConvertJ2735FrameToXML(messageFm); ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFm); string json_payload_str = xml2json(xml_payload_str.c_str()); - json["payload"] = TelematicBridgeMsgWorker::StringToJson(json_payload_str); + json["payload"] = StringToJson(json_payload_str); } - auto jsonStr = TelematicBridgeMsgWorker::JsonToString(json); + auto jsonStr = JsonToString(json); PLOG(logINFO) << jsonStr; } } diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicMsgWorker.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicMsgWorker.cpp index ac9494e64..dad8acbc8 100644 --- a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicMsgWorker.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicMsgWorker.cpp @@ -13,7 +13,7 @@ TEST_F(test_TelematicJ2735MsgWorker, HexToBytes) { vector byteBuff; string bsmHex = "0014251d59d162dad7de266e9a7d1ea6d4220974ffffffff8ffff080fdfa1fa1007fff0000640fa0"; - auto success = TelematicBridgeMsgWorker::HexToBytes(bsmHex, byteBuff); + auto success = HexToBytes(bsmHex, byteBuff); ASSERT_TRUE(success); ASSERT_EQ(bsmHex.size() / 2, byteBuff.size()); } @@ -22,7 +22,7 @@ TEST_F(test_TelematicJ2735MsgWorker, DecodeJ2735Msg) { auto messageFrame = (MessageFrame_t *)malloc(sizeof(MessageFrame_t)); string bsmHex = "0014251d59d162dad7de266e9a7d1ea6d4220974ffffffff8ffff080fdfa1fa1007fff0000640fa0"; - ASSERT_NO_THROW(TelematicBridgeMsgWorker::DecodeJ2735Msg(bsmHex, messageFrame)); + ASSERT_NO_THROW(DecodeJ2735Msg(bsmHex, messageFrame)); ASSERT_EQ(20, messageFrame->messageId); ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFrame); } @@ -31,10 +31,10 @@ TEST_F(test_TelematicJ2735MsgWorker, DecodeJ2735MsgFailure) { auto messageFrame = (MessageFrame_t *)malloc(sizeof(MessageFrame_t)); string badHex = "0014251d59d162dad7de266e9a7d1ea6d4220974ffffffff8ffff080fdfa1fa1007fff0000640fG0"; - ASSERT_THROW(TelematicBridgeMsgWorker::DecodeJ2735Msg(badHex, messageFrame), TelematicBridgeException); + ASSERT_THROW(DecodeJ2735Msg(badHex, messageFrame), TelematicBridgeException); badHex = "0014251d59d162dad7de266e9a"; - ASSERT_THROW(TelematicBridgeMsgWorker::DecodeJ2735Msg(badHex, messageFrame), TelematicBridgeException); + ASSERT_THROW(DecodeJ2735Msg(badHex, messageFrame), TelematicBridgeException); ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFrame); } @@ -42,8 +42,8 @@ TEST_F(test_TelematicJ2735MsgWorker, ConvertJ2735FrameToXML) { auto messageFrame = (MessageFrame_t *)malloc(sizeof(MessageFrame_t)); string bsmHex = "0014251d59d162dad7de266e9a7d1ea6d4220974ffffffff8ffff080fdfa1fa1007fff0000640fA0"; - ASSERT_NO_THROW(TelematicBridgeMsgWorker::DecodeJ2735Msg(bsmHex, messageFrame)); - auto xmlStr = TelematicBridgeMsgWorker::ConvertJ2735FrameToXML(messageFrame); + ASSERT_NO_THROW(DecodeJ2735Msg(bsmHex, messageFrame)); + auto xmlStr = ConvertJ2735FrameToXML(messageFrame); ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFrame); string expectedXMLStr = "2011767458B6B24440389565434-7715004757452552556553581912880012720012001-127000000200500"; ASSERT_EQ(expectedXMLStr, xmlStr); @@ -67,33 +67,33 @@ TEST_F(test_TelematicJ2735MsgWorker, constructTelematicPayload) metadata.channel = 12; metadata.psid = 120; msg.dsrcMetadata = &metadata; - auto json = TelematicBridgeMsgWorker::IvpMessageToJson(&msg); - auto str = TelematicBridgeMsgWorker::JsonToString(json); + auto json = IvpMessageToJson(&msg); + auto str = JsonToString(json); string expectedStr = "{\"channel\":12,\"encoding\":\"json\",\"flags\":10,\"payload\":12.0,\"psid\":120,\"source\":\"Plugin\",\"sourceId\":123,\"subType\":\"alive\",\"timestamp\":10,\"type\":\"Application\"}"; ASSERT_EQ(expectedStr, str); payload->valueint = 13; payload->type = cJSON_Number; msg.payload = payload; - json = TelematicBridgeMsgWorker::IvpMessageToJson(&msg); - str = TelematicBridgeMsgWorker::JsonToString(json); + json = IvpMessageToJson(&msg); + str = JsonToString(json); expectedStr = "{\"channel\":12,\"encoding\":\"json\",\"flags\":10,\"payload\":13.0,\"psid\":120,\"source\":\"Plugin\",\"sourceId\":123,\"subType\":\"alive\",\"timestamp\":10,\"type\":\"Application\"}"; ASSERT_EQ(expectedStr, str); payload->valuestring = "test"; payload->type = cJSON_String; msg.payload = payload; - json = TelematicBridgeMsgWorker::IvpMessageToJson(&msg); - str = TelematicBridgeMsgWorker::JsonToString(json); + json = IvpMessageToJson(&msg); + str = JsonToString(json); expectedStr = "{\"channel\":12,\"encoding\":\"json\",\"flags\":10,\"payload\":\"test\",\"psid\":120,\"source\":\"Plugin\",\"sourceId\":123,\"subType\":\"alive\",\"timestamp\":10,\"type\":\"Application\"}"; ASSERT_EQ(expectedStr, str); msg.payload = cJSON_Parse("[{\"test\":12}]"); - json = TelematicBridgeMsgWorker::IvpMessageToJson(&msg); - str = TelematicBridgeMsgWorker::JsonToString(json); + json = IvpMessageToJson(&msg); + str = JsonToString(json); expectedStr = "{\"channel\":12,\"encoding\":\"json\",\"flags\":10,\"payload\":[{\"test\":12}],\"psid\":120,\"source\":\"Plugin\",\"sourceId\":123,\"subType\":\"alive\",\"timestamp\":10,\"type\":\"Application\"}"; ASSERT_EQ(expectedStr, str); - json = TelematicBridgeMsgWorker::StringToJson("{\"test\":12}"); + json = StringToJson("{\"test\":12}"); ASSERT_EQ(12,json["test"].asInt64()); } \ No newline at end of file From a3b68aa8789a5a9d5e17bd3807628f4f76026d08 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 20 Nov 2023 15:23:40 +0000 Subject: [PATCH 14/48] address comments --- ext/build.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ext/build.sh b/ext/build.sh index 9347dceda..91d59ca8a 100755 --- a/ext/build.sh +++ b/ext/build.sh @@ -50,6 +50,9 @@ popd # GPS Parser pushd /tmp +if [ -d "NemaTode" ]; then + rm -r NemaTode +fi git clone https://github.com/ckgt/NemaTode.git cd NemaTode cmake . @@ -59,6 +62,9 @@ popd # Nats C API pushd /tmp +if [ -d "nats.c" ]; then + rm -r nats.c +fi git clone https://github.com/nats-io/nats.c cd nats.c cmake . -DNATS_BUILD_NO_SPIN=ON From 2f951d41e7e9218bc380608163d49b05c817aff3 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 20 Nov 2023 16:10:03 +0000 Subject: [PATCH 15/48] unnecessary log --- src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index 4dcd75828..bdc3f93c1 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -13,8 +13,6 @@ namespace TelematicBridge { if (msg && msg->type) { - PLOG(logDEBUG2) << "Message Received." - << " Type: " << msg->type << ", SubType: " << msg->subtype << ", DSRC metadata: " << msg->dsrcMetadata << ", encoding: " << msg->encoding << ", source: " << msg->source << ", sourceId: " << msg->sourceId << ", flags: " << msg->flags << ", timestamp: " << msg->timestamp << ", payload: " << cJSON_Print(msg->payload); auto json = IvpMessageToJson(msg); // Process J2735 message payload hex string if (strcasecmp(msg->type, Telematic_MSGTYPE_J2735_STRING) == 0) From 3c6143cf33a723e486282f4110ecbd9bf7ddfbcd Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 21 Nov 2023 17:55:33 +0000 Subject: [PATCH 16/48] init --- .../TelematicBridgePlugin/CMakeLists.txt | 2 +- .../TelematicBridgePlugin/manifest.json | 36 +++ src/v2i-hub/TelematicBridgePlugin/readme.md | 94 +++++++ .../src/TelematicBridgeMsgWorker.h | 1 + .../src/TelematicBridgePlugin.cpp | 45 ++- .../src/TelematicBridgePlugin.h | 16 +- .../src/TelematicUnit.cpp | 259 ++++++++++++++++++ .../TelematicBridgePlugin/src/TelematicUnit.h | 116 ++++++++ 8 files changed, 561 insertions(+), 8 deletions(-) create mode 100644 src/v2i-hub/TelematicBridgePlugin/readme.md create mode 100644 src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp create mode 100644 src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h diff --git a/src/v2i-hub/TelematicBridgePlugin/CMakeLists.txt b/src/v2i-hub/TelematicBridgePlugin/CMakeLists.txt index 5134ae38b..3b52f2660 100644 --- a/src/v2i-hub/TelematicBridgePlugin/CMakeLists.txt +++ b/src/v2i-hub/TelematicBridgePlugin/CMakeLists.txt @@ -3,7 +3,7 @@ PROJECT (TelematicBridgePlugin VERSION 7.5.1 LANGUAGES CXX) set (TMX_PLUGIN_NAME "Telematic Bridge") BuildTmxPlugin() -TARGET_LINK_LIBRARIES ( ${PROJECT_NAME} tmxutils jsoncpp) +TARGET_LINK_LIBRARIES ( ${PROJECT_NAME} tmxutils jsoncpp nats) #################################################### ################## Testing ####################### diff --git a/src/v2i-hub/TelematicBridgePlugin/manifest.json b/src/v2i-hub/TelematicBridgePlugin/manifest.json index 530dbe0eb..a78271c40 100644 --- a/src/v2i-hub/TelematicBridgePlugin/manifest.json +++ b/src/v2i-hub/TelematicBridgePlugin/manifest.json @@ -11,6 +11,42 @@ "key": "LogLevel", "default": "INFO", "description": "The log level for this plugin" + }, + { + "key": "NATSConnectionTimeOut", + "default": "1000", + "description": "The log level for this plugin" + + }, + { + "key": "NATSConnectionAttempts", + "default": "10", + "description": "The log level for this plugin" + + }, + { + "key": "NATSUrl", + "default": "nats://ec2-3-219-226-1.compute-1.amazonaws.com:4222", + "description": "The log level for this plugin" + + }, + { + "key": "UnitId", + "default": "v2xhub_id", + "description": "The log level for this plugin" + + }, + { + "key": "UnitName", + "default": "East Intersection", + "description": "The log level for this plugin" + + }, + { + "key": "UnitType", + "default": "Infrastructure", + "description": "The log level for this plugin" + } ] } \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/readme.md b/src/v2i-hub/TelematicBridgePlugin/readme.md new file mode 100644 index 000000000..87881fbec --- /dev/null +++ b/src/v2i-hub/TelematicBridgePlugin/readme.md @@ -0,0 +1,94 @@ +## NATS Publisher/Subscriber +### NATS Connections and registration +#### Telematic plugin sends registration request to telematic server +##### Subject +NATS subject: *.register_unit +##### Request +``` +{ + "unit_id": "" +} +``` +##### Response +``` +{ + "unit_id": "", + "unit_type": "infrastructure", + "unit_name": "East Intersection", + "timestamp": "1678998191815233965", + "event_name": "wfd_integration_testing", + "location": "TFHRC", + "testing_type": "Integration" +} +``` + +### Available topics +#### Telematic plugin receives request from telematic UI +##### Subject +NATS subject: .available_topics +##### Request +``` +{ + "unit_id": "" +} +``` +##### Reply + +``` + { + "unit_id": "", + "unit_type": "infrastructure", + "unit_name": "East Intersection", + "timestamp": "1678998191815233965", + "event_name": "wfd_integration_testing", + "location": "TFHRC", + "testing_type": "Integration", + "topics": [ + { + "name": "J2735_TMSG03-P_CARMAStreetsPlugin" + }, + { + "name": "" + } + ] +} +``` + +### Selected topics +#### Telematic plugin receives selected topics from telematic UI +##### Subject +NATS subject: .publish_topics +#### Request +``` +{ + "unit_id": "", + "unit_type": "infrastructure", + "timestamp": 1663084528513000400, + "event_name": "wfd_integration_testing", + "location": "TFHRC", + "testing_type": "Integration", + "topics": [ + "", + "" + ] +} +``` +##### Reply +``` +"request received!" +``` + +## Check status +#### Telematic plugin receives live status request from telematic server +##### Subject +NATS subject: .check_status +##### Request +``` +{ + "unit_id": "" +} +``` +##### Reponse +``` +"OK" +``` \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h index 551d171a4..32356c348 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h @@ -74,6 +74,7 @@ namespace TelematicBridge /** * Decode J2735 message */ + // messageFrame = (MessageFrame_t *)malloc(sizeof(MessageFrame_t)); ostringstream erroross; vector byte_buffer; if (!HexToBytes(hexPaylod, byte_buffer)) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index bdc3f93c1..9a9a914e9 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -4,6 +4,8 @@ namespace TelematicBridge { TelematicBridgePlugin::TelematicBridgePlugin(const string &name) : PluginClient(name) { + _telematicUnitPtr = make_shared(); + UpdateConfigSettings(); AddMessageFilter("*", "*", IvpMsgFlags_None); AddMessageFilter("J2735", "*", IvpMsgFlags_RouteDSRC); SubscribeToMessages(); @@ -17,16 +19,51 @@ namespace TelematicBridge // Process J2735 message payload hex string if (strcasecmp(msg->type, Telematic_MSGTYPE_J2735_STRING) == 0) { - auto messageFm = (MessageFrame_t *)malloc(sizeof(MessageFrame_t)); + auto messageFm = (MessageFrame_t *)calloc(1, sizeof(MessageFrame_t)); DecodeJ2735Msg(msg->payload->valuestring, messageFm); string xml_payload_str = ConvertJ2735FrameToXML(messageFm); - ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFm); + // ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFm); string json_payload_str = xml2json(xml_payload_str.c_str()); json["payload"] = StringToJson(json_payload_str); } - auto jsonStr = JsonToString(json); - PLOG(logINFO) << jsonStr; + stringstream topic; + topic << (msg->type ? msg->type : "") << "_" << (msg->subtype ? msg->subtype : "") << "_" << (msg->source ? msg->source : ""); + auto topicStr = topic.str(); + _telematicUnitPtr->updateAvailableTopics(topicStr); + if (_telematicUnitPtr->inSelectedTopics(topicStr)) + { + _telematicUnitPtr->publishMessage(topicStr, json); + } + } + } + + void TelematicBridgePlugin::UpdateConfigSettings() + { + lock_guard lock(_configMutex); + GetConfigValue("NATSConnectionTimeOut", _natsConnTimeOut); + GetConfigValue("NATSConnectionAttempts", _natsConnAttempts); + GetConfigValue("NATSUrl", _natsURL); + GetConfigValue("UnitId", _unitId); + GetConfigValue("UnitName", _unitName); + GetConfigValue("UnitType", _unitType); + unit_st unit; + unit.unitId = _unitId; + unit.unitName = _unitName; + unit.unitType = _unitType; + if (_telematicUnitPtr) + { + _telematicUnitPtr->setUnit(unit); + } + } + + void TelematicBridgePlugin::OnConfigChanged(const char *key, const char *value) + { + PluginClient::OnConfigChanged(key, value); + UpdateConfigSettings(); + if (_telematicUnitPtr) + { + _telematicUnitPtr->connect(_natsURL, _natsConnAttempts, _natsConnTimeOut); } } } diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h index 0953ccd90..10f003421 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h @@ -3,22 +3,32 @@ #include "PluginClient.h" #include "TelematicBridgeMsgWorker.h" +#include "TelematicUnit.h" #include "xml2json.h" using namespace tmx::utils; using namespace std; namespace TelematicBridge { - - class TelematicBridgePlugin : public tmx::utils::PluginClient { private: static CONSTEXPR const char *Telematic_MSGTYPE_J2735_STRING = "J2735"; + shared_ptr _telematicUnitPtr; + int _natsConnAttempts; + //The time, in milliseconds, allowed for an individual connect (or reconnect) to complete. + int64_t _natsConnTimeOut; + string _unitId; + string _unitType; + string _unitName; + string _natsURL; + mutex _configMutex; void OnMessageReceived(IvpMessage *msg); public: - explicit TelematicBridgePlugin(const string& name); + explicit TelematicBridgePlugin(const string &name); + void OnConfigChanged(const char *key, const char *value) override; + void UpdateConfigSettings(); ~TelematicBridgePlugin() override = default; }; diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp new file mode 100644 index 000000000..7fed58f6f --- /dev/null +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp @@ -0,0 +1,259 @@ +#include "TelematicUnit.h" + +namespace TelematicBridge +{ + TelematicUnit::TelematicUnit() + { + // natsStatus s; + // s = natsOptions_SetTimeout(_opts, natsConnTimeout); + // if (s == NATS_OK) + // { + // natsOptions_SetMaxReconnect(_opts, natsConnAttempts); + // } + + // if (s == NATS_OK) + // { + // s = natsOptions_SetRetryOnFailedConnect(_opts, true, nullptr, nullptr); + // } + + // if (s == NATS_OK) + // { + // s = natsOptions_SetURL(_opts, natsURL); + // } + + // if (s != NATS_OK) + // { + // nats_PrintLastErrorStack(stderr); + // throw TelematicBridgeException(natsStatus_GetText(s)); + // } + } + + void TelematicUnit::connect(const string &natsURL, uint16_t natsConnAttempts, uint16_t natsConnTimeout) + { + if (!isConnected) + { + PLOG(logINFO) << "Trying to connect to " << natsURL << " attempts: " << natsConnAttempts << ", nats connect timeout: " << natsConnTimeout; + // auto s = natsConnection_Connect(&_conn, _opts); + auto s = natsConnection_ConnectTo(&_conn, natsURL.c_str()); + PLOG(logINFO) << "natsConnection_Connect returned: " << natsStatus_GetText(s); + if (s == NATS_OK) + { + isConnected = true; + registerUnitRequestor(); + } + else + { + isConnected = false; + nats_PrintLastErrorStack(stderr); + printf("NATS Connection Error: %u - %s\n", s, natsStatus_GetText(s)); + throw TelematicBridgeException(natsStatus_GetText(s)); + } + } + } + + void TelematicUnit::setUnit(unit_st unit) + { + lock_guard lock(_unitMutex); + _unit = unit; + } + + void TelematicUnit::updateAvailableTopics(const string &newTopic) + { + if (find(availableTopics.begin(), availableTopics.end(), newTopic) == availableTopics.end()) + { + lock_guard lock(_availableTopicsMutex); + availableTopics.push_back(newTopic); + PLOG(logDEBUG2) << "Add topic (= " << newTopic << ") to available topics list. Size: " << availableTopics.size(); + } + } + + void TelematicUnit::registerUnitRequestor() + { + while (!isRegistered) + { + PLOG(logINFO) << "Inside register unit requestor"; + natsMsg *reply = nullptr; + string payload = "{\"unit_id\":\"" + _unit.unitId + "\"}"; + auto s = natsConnection_RequestString(&reply, _conn, REGISTER_UNIT_TOPIC, payload.c_str(), TIME_OUT); + if (s == NATS_OK) + { + isRegistered = true; + PLOG(logINFO) << "Received regitered reply: " << natsMsg_GetData(reply); + Json::Value root; + Json::Reader reader; + bool parsingSuccessful = reader.parse(natsMsg_GetData(reply), root); + if (!parsingSuccessful) + { + throw TelematicBridgeException("Error parsing the reply message"); + } + if (root.isMember("location")) + { + _eventLocation = root["location"].asString(); + } + if (root.isMember("location")) + { + _testingType = root["testing_type"].asString(); + } + if (root.isMember("event_name")) + { + _eventName = root["event_name"].asString(); + } + availableTopicsReplier(); + selectedTopicsReplier(); + checkStatusReplier(); + } + else + { + isRegistered = false; + nats_PrintLastErrorStack(stderr); + printf("NATS regiter Error: %u - %s\n", s, natsStatus_GetText(s)); + } + natsMsg_Destroy(reply); + } + } + + void TelematicUnit::availableTopicsReplier() + { + if (!subAvailableTopic) + { + PLOG(logDEBUG2) << "Inside available topic replier"; + stringstream topic; + topic << _unit.unitId << AVAILABLE_TOPICS; + auto s = natsConnection_Subscribe(&subAvailableTopic, _conn, topic.str().c_str(), onAvailableTopicsCallback, this); + } + } + + void TelematicUnit::selectedTopicsReplier() + { + if (!subSelectedTopic) + { + PLOG(logDEBUG2) << "Inside selected topic replier"; + stringstream topic; + topic << _unit.unitId << PUBLISH_TOPICS; + auto s = natsConnection_Subscribe(&subSelectedTopic, _conn, topic.str().c_str(), onSelectedTopicsCallback, this); + } + } + + void TelematicUnit::checkStatusReplier() + { + if (!subCheckStatus) + { + PLOG(logDEBUG2) << "Inside check status replier"; + stringstream topic; + topic << _unit.unitId << CHECK_STATUS; + auto s = natsConnection_Subscribe(&subCheckStatus, _conn, topic.str().c_str(), onCheckStatusCallback, this); + } + } + + void TelematicUnit::publishMessage(const string &topic, const Json::Value &payload) + { + auto pubMsgTopic = "streets." + _unit.unitId + ".data." + topic; + Json::Value message; + message["unit_id"] = _unit.unitId; + message["unit_name"] = _unit.unitName; + message["unit_type"] = _unit.unitType; + message["location"] = _eventLocation; + message["testing_type"] = _testingType; + message["event_name"] = _eventName; + message["topic_name"] = topic; + message["timestamp"] = duration_cast(system_clock::now().time_since_epoch()).count(); + message["payload"] = payload; + Json::FastWriter fasterWirter; + string jsonStr = fasterWirter.write(message); + auto s = natsConnection_PublishString(_conn, pubMsgTopic.c_str(), jsonStr.c_str()); + if (s != NATS_OK) + { + PLOG(logINFO) << "Topic: " << pubMsgTopic << ". Published: " << jsonStr; + } + else + { + nats_PrintLastErrorStack(stderr); + throw TelematicBridgeException(natsStatus_GetText(s)); + } + } + + bool TelematicUnit::inSelectedTopics(const string &topic) + { + if (find(selectedTopics.begin(), selectedTopics.end(), topic) == selectedTopics.end()) + { + return false; + } + return true; + } + + void TelematicUnit::onAvailableTopicsCallback(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *object) + { + PLOG(logDEBUG3) << "Received available topics: " << natsMsg_GetSubject(msg) << " " << natsMsg_GetData(msg); + // Sends a reply + if (natsMsg_GetReply(msg) != NULL) + { + TelematicUnit *obj = (TelematicUnit *)object; + Json::Value payload; + payload["unit_id"] = obj->_unit.unitId; + payload["unit_name"] = obj->_unit.unitName; + payload["unit_type"] = obj->_unit.unitType; + payload["timestamp"] = duration_cast(system_clock::now().time_since_epoch()).count(); + Json::Value topics; + for (const auto &topic : obj->availableTopics) + { + Json::Value topicJson; + topicJson["name"] = topic; + topics.append(topicJson); + } + payload["topics"] = topics; + Json::FastWriter fasterWirter; + string jsonStr = fasterWirter.write(payload); + PLOG(logDEBUG2) << "Available topics replied! " << jsonStr; + natsConnection_PublishString(nc, natsMsg_GetReply(msg), jsonStr.c_str()); + } + natsMsg_Destroy(msg); + } + + void TelematicUnit::onSelectedTopicsCallback(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *object) + { + PLOG(logDEBUG3) << "Received selected topics: " << natsMsg_GetSubject(msg) << " " << natsMsg_GetData(msg); + // Sends a reply + if (natsMsg_GetReply(msg) != NULL) + { + TelematicUnit *obj = (TelematicUnit *)object; + Json::Value root; + Json::Reader reader; + auto msgStr = natsMsg_GetData(msg); + bool parsingSuccessful = reader.parse(msgStr, root); + if (!parsingSuccessful) + { + throw TelematicBridgeException("Error parsing the string"); + } + if (root["topics"].isArray()) + { + for (auto itr = root["topics"].begin(); itr != root["topics"].end(); itr++) + { + obj->selectedTopics.push_back(itr->asString()); + } + } + string payload = "request received!"; + PLOG(logDEBUG2) << "Selected topics replied: " << payload; + natsConnection_PublishString(nc, natsMsg_GetReply(msg), payload.c_str()); + } + natsMsg_Destroy(msg); + } + + void TelematicUnit::onCheckStatusCallback(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *object) + { + if (natsMsg_GetReply(msg) != NULL) + { + PLOG(logDEBUG3) << "Received check status msg: " << natsMsg_GetSubject(msg) << " " << natsMsg_GetData(msg); + string payload = "OK"; + PLOG(logDEBUG3) << "Status Check: " << payload; + natsConnection_PublishString(nc, natsMsg_GetReply(msg), payload.c_str()); + natsMsg_Destroy(msg); + } + } + + TelematicUnit::~TelematicUnit() + { + natsOptions_Destroy(_opts); + natsConnection_Destroy(_conn); + _conn = nullptr; + } +} \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h new file mode 100644 index 000000000..c39d7d698 --- /dev/null +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h @@ -0,0 +1,116 @@ +#pragma once +#include +#include +#include +#include +#include +#include "PluginLog.h" +#include "ThreadTimer.h" +#include "TelematicBridgeException.h" +#include + +using namespace std; +using namespace tmx::utils; +using namespace std::chrono; + +namespace TelematicBridge +{ + using unit_st = struct unit + { + string unitId; // Unique identifier for each unit + string unitType; // Unit categorized base on unit type: platform or infrastructure + string unitName; // Descriptive name for each unit + }; + + class TelematicUnit + { + public: + mutex _unitMutex; + mutex _availableTopicsMutex; + atomic isConnected {false}; + atomic isRegistered{false}; + unit_st _unit; // Global variable to store the unit information + vector availableTopics; // Global variable to store available topics + vector selectedTopics; // Global variable to store selected topics confirmed by users + static CONSTEXPR const char *AVAILABLE_TOPICS = ".available_topics"; // NATS subject to pub/sub available topics + static CONSTEXPR const char *REGISTER_UNIT_TOPIC = "*.register_unit"; // NATS subject to pub/sub registering unit + static CONSTEXPR const char *PUBLISH_TOPICS = ".publish_topics"; // NATS subject to publish data stream + static CONSTEXPR const char *CHECK_STATUS = ".check_status"; // NATS subject to pub/sub checking unit status + unique_ptr _natsRegisterTh; + natsConnection *_conn = nullptr; // Global NATS connection object + natsOptions *_opts = nullptr; + natsSubscription *subAvailableTopic = nullptr; + natsSubscription *subSelectedTopic = nullptr; + natsSubscription *subCheckStatus = nullptr; + int64_t TIME_OUT = 10000; + string _eventName; + string _eventLocation; + string _testingType; + + /** + *@brief Construct telematic unit + */ + explicit TelematicUnit(); + /** + * @brief A function for telematic unit to connect to NATS server. Throw exception is connection failed. * + * @param const string NATS server URL + * @param uint16_t The numbers of attempts to make connections to NATS server + * @param uint16_t The timeout for between connection attempts + */ + void connect(const string &natsURL, uint16_t natsConnAttempts, uint16_t natsConnTimeout); + + /** + * @brief A function to update available topics global variables when discovering a new topic. + */ + void updateAvailableTopics(const string &newTopic); + + /** + * @brief A function to publish message stream into NATS server + */ + void publishMessage(const string &topic, const Json::Value &payload); + + /** + * @brief A function to update global unit variable + * @param unit_st object that has the unit id, type and name information + */ + void setUnit(unit_st unit); + + /** + * @brief Check if the given topic is inside the selectedTopics list + * @param string A topic to check for existence + * @return boolean indicator whether the input topic eixst. + */ + bool inSelectedTopics(const string& topic); + + /** + * @brief A NATS requestor for telematic unit to send register request to NATS server. + * If receives a response, it will update the isRegistered flag to indicate the unit is registered. + * If no response after the specified time out (unit of second) period, it considered register failed. + * */ + void registerUnitRequestor(); + + /** + * @brief A NATS replier to publish available topics upon receiving a request for a list of available topics. + */ + void availableTopicsReplier(); + + /** + * @brief A NATS replier to subscribe to NATS server and receive requested topics from telematic server. + * Process the request and update the selectedTopics global variable. + * Respond the telematic server with acknowledgement. + */ + void selectedTopicsReplier(); + + /** + * @brief A NATS replier to publish unit status upon receiving a request for status check from telematic server. + */ + void checkStatusReplier(); + + static void onAvailableTopicsCallback(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *object); + static void onSelectedTopicsCallback(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *object); + static void onCheckStatusCallback(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *object); + + ~TelematicUnit(); + }; + +} // namespace TelematicBridge From 9e63a6a5d76eebf71217d122908c3e50dfc38fb0 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 21 Nov 2023 18:19:08 +0000 Subject: [PATCH 17/48] address comments --- .../src/TelematicBridgePlugin.cpp | 11 +- .../src/TelematicBridgePlugin.h | 5 +- .../TelematicBridgePlugin/src/xml2json.h | 265 ------------------ .../test/test_xml2json.cpp | 22 +- 4 files changed, 25 insertions(+), 278 deletions(-) delete mode 100644 src/v2i-hub/TelematicBridgePlugin/src/xml2json.h diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index bdc3f93c1..e61c5c44b 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -17,12 +17,17 @@ namespace TelematicBridge // Process J2735 message payload hex string if (strcasecmp(msg->type, Telematic_MSGTYPE_J2735_STRING) == 0) { - auto messageFm = (MessageFrame_t *)malloc(sizeof(MessageFrame_t)); + auto messageFm = (MessageFrame_t *)calloc(1, sizeof(MessageFrame_t)); DecodeJ2735Msg(msg->payload->valuestring, messageFm); string xml_payload_str = ConvertJ2735FrameToXML(messageFm); ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFm); - string json_payload_str = xml2json(xml_payload_str.c_str()); - json["payload"] = StringToJson(json_payload_str); + stringstream xmlss; + xmlss << xml_payload_str; + pt::ptree root; + pt::read_xml(xmlss, root); + stringstream jsonss; + pt::write_json(jsonss, root, false); + json["payload"] = StringToJson(jsonss.str()); } auto jsonStr = JsonToString(json); diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h index 0953ccd90..e6d30a22a 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h @@ -3,10 +3,13 @@ #include "PluginClient.h" #include "TelematicBridgeMsgWorker.h" -#include "xml2json.h" +#include +#include +#include using namespace tmx::utils; using namespace std; +namespace pt = boost::property_tree; namespace TelematicBridge { diff --git a/src/v2i-hub/TelematicBridgePlugin/src/xml2json.h b/src/v2i-hub/TelematicBridgePlugin/src/xml2json.h deleted file mode 100644 index c22a3053d..000000000 --- a/src/v2i-hub/TelematicBridgePlugin/src/xml2json.h +++ /dev/null @@ -1,265 +0,0 @@ -#ifndef XML2JSON_HPP_INCLUDED -#define XML2JSON_HPP_INCLUDED - -// Refer to https://github.com/Cheedoong/xml2json/blob/master/include/xml2json.hpp - -#include -#include -#include -#include - -#include "rapidxml/rapidxml.hpp" -#include "rapidxml/rapidxml_utils.hpp" -#include "rapidxml/rapidxml_print.hpp" - -#include "rapidjson/document.h" -#include "rapidjson/prettywriter.h" -#include "rapidjson/encodedstream.h" -#include "rapidjson/stringbuffer.h" -#include "rapidjson/reader.h" -#include "rapidjson/writer.h" -#include "rapidjson/filereadstream.h" -#include "rapidjson/filewritestream.h" -#include "rapidjson/error/en.h" - -/* [Start] This part is configurable */ -static const char xml2json_text_additional_name[] = "#text"; -static const char xml2json_attribute_name_prefix[] = "@"; -/* Example: - value ---> "node_name":{"#text":"value","@attribute_name":"attribute_value"} -*/ -static const bool xml2json_numeric_support = true; -/* Example: - xml2json_numeric_support = false: - 26.026 ---> "number":"26.026" - xml2json_numeric_support = true: - 26.026 ---> "number":26.026 -*/ -/* [End] This part is configurable */ - -// Avoided any namespace pollution. -static bool xml2json_has_digits_only(const char *input, bool *hasDecimal) -{ - if (input == nullptr) - return false; // treat empty input as a string (probably will be an empty string) - - const char *runPtr = input; - - *hasDecimal = false; - - while (*runPtr != '\0') - { - if (*runPtr == '.') - { - if (!(*hasDecimal)) - *hasDecimal = true; - else - return false; // we found two dots - not a number - } - else if (isalpha(*runPtr)) - { - return false; - } - runPtr++; - } - - return true; -} - -void xml2json_to_array_form(const char *name, rapidjson::Value &jsvalue, rapidjson::Value &jsvalue_chd, rapidjson::Document::AllocatorType &allocator) -{ - rapidjson::Value jsvalue_target; // target to do some operation - rapidjson::Value jn; // this is a must, partially because of the latest version of rapidjson - jn.SetString(name, allocator); - jsvalue_target = jsvalue.FindMember(name)->value; - if (jsvalue_target.IsArray()) - { - jsvalue_target.PushBack(jsvalue_chd, allocator); - jsvalue.RemoveMember(name); - jsvalue.AddMember(jn, jsvalue_target, allocator); - } - else - { - rapidjson::Value jsvalue_array; - jsvalue_array.SetArray(); - jsvalue_array.PushBack(jsvalue_target, allocator); - jsvalue_array.PushBack(jsvalue_chd, allocator); - jsvalue.RemoveMember(name); - jsvalue.AddMember(jn, jsvalue_array, allocator); - } -} - -void xml2json_add_attributes(const rapidxml::xml_node<> *xmlnode, rapidjson::Value &jsvalue, rapidjson::Document::AllocatorType &allocator) -{ - for (auto myattr = xmlnode->first_attribute(); myattr; myattr = myattr->next_attribute()) - { - rapidjson::Value jn; - rapidjson::Value jv; - jn.SetString((std::string(xml2json_attribute_name_prefix) + myattr->name()).c_str(), allocator); - - if (xml2json_numeric_support == false) - { - jv.SetString(myattr->value(), allocator); - } - else - { - bool hasDecimal; - if (xml2json_has_digits_only(myattr->value(), &hasDecimal) == false) - { - jv.SetString(myattr->value(), allocator); - } - else - { - if (hasDecimal) - { - double value = std::strtod(myattr->value(), nullptr); - jv.SetDouble(value); - } - else - { - long int value = std::strtol(myattr->value(), nullptr, 0); - jv.SetInt(static_cast(value)); - } - } - } - jsvalue.AddMember(jn, jv, allocator); - } -} - -void xml2json_traverse_node(rapidxml::xml_node<> *xmlnode, rapidjson::Value &jsvalue, rapidjson::Document::AllocatorType &allocator) -{ - rapidjson::Value jsvalue_chd; - - jsvalue.SetObject(); - jsvalue_chd.SetObject(); - - // classified discussion: - if ((xmlnode->type() == rapidxml::node_data || xmlnode->type() == rapidxml::node_cdata) && xmlnode->value()) - { - // case: pure_text - jsvalue.SetString(xmlnode->value(), allocator); // then addmember("#text" , jsvalue, allocator) - } - else if (xmlnode->type() == rapidxml::node_element) - { - if (xmlnode->first_attribute()) - { - if (xmlnode->first_node() && xmlnode->first_node()->type() == rapidxml::node_data && count_children(xmlnode) == 1) - { - // case: text - rapidjson::Value jn; - rapidjson::Value jv; - jn.SetString(xml2json_text_additional_name, allocator); - jv.SetString(xmlnode->first_node()->value(), allocator); - jsvalue.AddMember(jn, jv, allocator); - xml2json_add_attributes(xmlnode, jsvalue, allocator); - return; - } - else - { - // case: ... - xml2json_add_attributes(xmlnode, jsvalue, allocator); - } - } - else - { - if (!xmlnode->first_node()) - { - // case: - jsvalue.SetNull(); - return; - } - else if (xmlnode->first_node()->type() == rapidxml::node_data && count_children(xmlnode) == 1) - { - // case: text - if (xml2json_numeric_support == false) - { - jsvalue.SetString(rapidjson::StringRef(xmlnode->first_node()->value()), allocator); - } - else - { - bool hasDecimal; - if (xml2json_has_digits_only(xmlnode->first_node()->value(), &hasDecimal) == false) - { - jsvalue.SetString(rapidjson::StringRef(xmlnode->first_node()->value()), allocator); - } - else - { - if (hasDecimal) - { - double value = std::strtod(xmlnode->first_node()->value(), nullptr); - jsvalue.SetDouble(value); - } - else - { - long int value = std::strtol(xmlnode->first_node()->value(), nullptr, 0); - jsvalue.SetInt(static_cast(value)); - } - } - } - return; - } - } - if (xmlnode->first_node()) - { - // case: complex else... - std::map name_count; - for (auto xmlnode_chd = xmlnode->first_node(); xmlnode_chd; xmlnode_chd = xmlnode_chd->next_sibling()) - { - std::string current_name; - const char *name_ptr = nullptr; - rapidjson::Value jn; - rapidjson::Value jv; - if (xmlnode_chd->type() == rapidxml::node_data || xmlnode_chd->type() == rapidxml::node_cdata) - { - current_name = xml2json_text_additional_name; - name_count[current_name]++; - jv.SetString(xml2json_text_additional_name, allocator); - name_ptr = jv.GetString(); - } - else if (xmlnode_chd->type() == rapidxml::node_element) - { - current_name = xmlnode_chd->name(); - name_count[current_name]++; - name_ptr = xmlnode_chd->name(); - } - xml2json_traverse_node(xmlnode_chd, jsvalue_chd, allocator); - if (name_count[current_name] > 1 && name_ptr) - xml2json_to_array_form(name_ptr, jsvalue, jsvalue_chd, allocator); - else - { - jn.SetString(name_ptr, allocator); - jsvalue.AddMember(jn, jsvalue_chd, allocator); - } - } - } - } - else - { - std::cerr << "err data!!" << std::endl; - } -} - -std::string xml2json(const char *xml_str) -{ - auto xml_doc = std::make_unique>(); - xml_doc->parse<0>(const_cast(xml_str)); - - rapidjson::Document js_doc; - js_doc.SetObject(); - rapidjson::Document::AllocatorType &allocator = js_doc.GetAllocator(); - - for (auto xmlnode_chd = xml_doc->first_node(); xmlnode_chd; xmlnode_chd = xmlnode_chd->next_sibling()) - { - rapidjson::Value jsvalue_chd; - jsvalue_chd.SetObject(); - xml2json_traverse_node(xmlnode_chd, jsvalue_chd, allocator); - js_doc.AddMember(rapidjson::StringRef(xmlnode_chd->name()), jsvalue_chd, allocator); - } - - rapidjson::StringBuffer buffer; - rapidjson::Writer writer(buffer); - js_doc.Accept(writer); - return buffer.GetString(); -} - -#endif \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp index 9ade6eb9f..4defac1cc 100644 --- a/src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp @@ -1,8 +1,12 @@ #include -#include "xml2json.h" +// #include "xml2json.h" #include "stdio.h" +#include +#include +#include using namespace std; +namespace pt = boost::property_tree; class test_xml2json : public ::testing::Test { @@ -11,12 +15,12 @@ class test_xml2json : public ::testing::Test TEST_F(test_xml2json, xml2json) { string expectedXMLStr = "2011767458B6B24440389565434-7715004757452552556553581912880012720012001-127000000200500"; - auto json = xml2json(expectedXMLStr.c_str()); - string expectedJSONStr = "{\"MessageFrame\":{\"messageId\":20,\"value\":{\"BasicSafetyMessage\":{\"coreData\":{\"msgCnt\":117,\"id\":\"67458B6B\",\"secMark\":24440,\"lat\":389565434,\"long\":-771500475,\"elev\":745,\"accuracy\":{\"semiMajor\":255,\"semiMinor\":255,\"orientation\":65535},\"transmission\":{\"neutral\":null},\"speed\":8191,\"heading\":28800,\"angle\":127,\"accelSet\":{\"long\":2001,\"lat\":2001,\"vert\":-127,\"yaw\":0},\"brakes\":{\"wheelBrakes\":0,\"traction\":{\"unavailable\":null},\"abs\":{\"unavailable\":null},\"scs\":{\"unavailable\":null},\"brakeBoost\":{\"unavailable\":null},\"auxBrakes\":{\"unavailable\":null}},\"size\":{\"width\":200,\"length\":500}}}}}}"; - ASSERT_EQ(expectedJSONStr, json); - - expectedXMLStr = "1234567890a1234567890a1234567890a"; - json = xml2json(expectedXMLStr.c_str()); - expectedJSONStr ="{\"tl\":{\"@attr\":\"added attr\",\"null_node_without_attr\":null,\"id\":[{\"#text\":\"1234567890a\",\"@tid\":\"added tid\"},{\"#text\":\"1234567890a\",\"@tid\":12.3},{\"#text\":\"1234567890a\",\"@tid\":12}]}}"; - ASSERT_EQ(json , expectedJSONStr); + stringstream xmlss; + xmlss << expectedXMLStr; + pt::ptree root; + pt::read_xml(xmlss, root); + stringstream jsonss; + pt::write_json(jsonss, root, false); + string expectedJSONStr = "{\"MessageFrame\":{\"messageId\":\"20\",\"value\":{\"BasicSafetyMessage\":{\"coreData\":{\"msgCnt\":\"117\",\"id\":\"67458B6B\",\"secMark\":\"24440\",\"lat\":\"389565434\",\"long\":\"-771500475\",\"elev\":\"745\",\"accuracy\":{\"semiMajor\":\"255\",\"semiMinor\":\"255\",\"orientation\":\"65535\"},\"transmission\":{\"neutral\":\"\"},\"speed\":\"8191\",\"heading\":\"28800\",\"angle\":\"127\",\"accelSet\":{\"long\":\"2001\",\"lat\":\"2001\",\"vert\":\"-127\",\"yaw\":\"0\"},\"brakes\":{\"wheelBrakes\":\"00000\",\"traction\":{\"unavailable\":\"\"},\"abs\":{\"unavailable\":\"\"},\"scs\":{\"unavailable\":\"\"},\"brakeBoost\":{\"unavailable\":\"\"},\"auxBrakes\":{\"unavailable\":\"\"}},\"size\":{\"width\":\"200\",\"length\":\"500\"}}}}}}\n"; + ASSERT_EQ(expectedJSONStr, jsonss.str()); } \ No newline at end of file From 31f0be38f209f809ebef5a581609b4b1905dad8e Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 21 Nov 2023 18:24:40 +0000 Subject: [PATCH 18/48] address comments --- .../src/TelematicBridgeMsgWorker.h | 17 ++++++++++++ .../src/TelematicBridgePlugin.cpp | 10 ++----- .../src/TelematicBridgePlugin.h | 4 --- .../test/test_TelematicMsgWorker.cpp | 9 ++++++- .../test/test_xml2json.cpp | 26 ------------------- 5 files changed, 27 insertions(+), 39 deletions(-) delete mode 100644 src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h index 551d171a4..c31c5cc9c 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgeMsgWorker.h @@ -4,10 +4,14 @@ #include "TelematicBridgeException.h" #include "jsoncpp/json/json.h" #include +#include +#include +#include using namespace tmx::utils; using namespace std; using namespace tmx::messages; +namespace pt = boost::property_tree; namespace TelematicBridge { @@ -177,6 +181,19 @@ namespace TelematicBridge } return root; } + /** + * @brief Convert XML string into JSON string + */ + string xml2Json(const string &xml_str) + { + stringstream xmlss; + xmlss << xml_str; + pt::ptree root; + pt::read_xml(xmlss, root); + stringstream jsonss; + pt::write_json(jsonss, root, false); + return jsonss.str(); + } /** * @brief create JSON payload from given IVP message * @param IVPMessage V2xHub interval exchanged message diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index e61c5c44b..a316084f4 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -20,14 +20,8 @@ namespace TelematicBridge auto messageFm = (MessageFrame_t *)calloc(1, sizeof(MessageFrame_t)); DecodeJ2735Msg(msg->payload->valuestring, messageFm); string xml_payload_str = ConvertJ2735FrameToXML(messageFm); - ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFm); - stringstream xmlss; - xmlss << xml_payload_str; - pt::ptree root; - pt::read_xml(xmlss, root); - stringstream jsonss; - pt::write_json(jsonss, root, false); - json["payload"] = StringToJson(jsonss.str()); + ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFm); + json["payload"] = StringToJson(xml2Json(xml_payload_str)); } auto jsonStr = JsonToString(json); diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h index e6d30a22a..c790b6ca4 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h @@ -3,13 +3,9 @@ #include "PluginClient.h" #include "TelematicBridgeMsgWorker.h" -#include -#include -#include using namespace tmx::utils; using namespace std; -namespace pt = boost::property_tree; namespace TelematicBridge { diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicMsgWorker.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicMsgWorker.cpp index dad8acbc8..9760ec906 100644 --- a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicMsgWorker.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicMsgWorker.cpp @@ -95,5 +95,12 @@ TEST_F(test_TelematicJ2735MsgWorker, constructTelematicPayload) ASSERT_EQ(expectedStr, str); json = StringToJson("{\"test\":12}"); - ASSERT_EQ(12,json["test"].asInt64()); + ASSERT_EQ(12, json["test"].asInt64()); +} + +TEST_F(test_TelematicJ2735MsgWorker, xml2json) +{ + string expectedXMLStr = "2011767458B6B24440389565434-7715004757452552556553581912880012720012001-127000000200500"; + string expectedJSONStr = "{\"MessageFrame\":{\"messageId\":\"20\",\"value\":{\"BasicSafetyMessage\":{\"coreData\":{\"msgCnt\":\"117\",\"id\":\"67458B6B\",\"secMark\":\"24440\",\"lat\":\"389565434\",\"long\":\"-771500475\",\"elev\":\"745\",\"accuracy\":{\"semiMajor\":\"255\",\"semiMinor\":\"255\",\"orientation\":\"65535\"},\"transmission\":{\"neutral\":\"\"},\"speed\":\"8191\",\"heading\":\"28800\",\"angle\":\"127\",\"accelSet\":{\"long\":\"2001\",\"lat\":\"2001\",\"vert\":\"-127\",\"yaw\":\"0\"},\"brakes\":{\"wheelBrakes\":\"00000\",\"traction\":{\"unavailable\":\"\"},\"abs\":{\"unavailable\":\"\"},\"scs\":{\"unavailable\":\"\"},\"brakeBoost\":{\"unavailable\":\"\"},\"auxBrakes\":{\"unavailable\":\"\"}},\"size\":{\"width\":\"200\",\"length\":\"500\"}}}}}}\n"; + ASSERT_EQ(expectedJSONStr, xml2Json(expectedXMLStr)); } \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp deleted file mode 100644 index 4defac1cc..000000000 --- a/src/v2i-hub/TelematicBridgePlugin/test/test_xml2json.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include -// #include "xml2json.h" -#include "stdio.h" -#include -#include -#include - -using namespace std; -namespace pt = boost::property_tree; - -class test_xml2json : public ::testing::Test -{ -}; - -TEST_F(test_xml2json, xml2json) -{ - string expectedXMLStr = "2011767458B6B24440389565434-7715004757452552556553581912880012720012001-127000000200500"; - stringstream xmlss; - xmlss << expectedXMLStr; - pt::ptree root; - pt::read_xml(xmlss, root); - stringstream jsonss; - pt::write_json(jsonss, root, false); - string expectedJSONStr = "{\"MessageFrame\":{\"messageId\":\"20\",\"value\":{\"BasicSafetyMessage\":{\"coreData\":{\"msgCnt\":\"117\",\"id\":\"67458B6B\",\"secMark\":\"24440\",\"lat\":\"389565434\",\"long\":\"-771500475\",\"elev\":\"745\",\"accuracy\":{\"semiMajor\":\"255\",\"semiMinor\":\"255\",\"orientation\":\"65535\"},\"transmission\":{\"neutral\":\"\"},\"speed\":\"8191\",\"heading\":\"28800\",\"angle\":\"127\",\"accelSet\":{\"long\":\"2001\",\"lat\":\"2001\",\"vert\":\"-127\",\"yaw\":\"0\"},\"brakes\":{\"wheelBrakes\":\"00000\",\"traction\":{\"unavailable\":\"\"},\"abs\":{\"unavailable\":\"\"},\"scs\":{\"unavailable\":\"\"},\"brakeBoost\":{\"unavailable\":\"\"},\"auxBrakes\":{\"unavailable\":\"\"}},\"size\":{\"width\":\"200\",\"length\":\"500\"}}}}}}\n"; - ASSERT_EQ(expectedJSONStr, jsonss.str()); -} \ No newline at end of file From dccd1bef3fb420e2b28b3283dab6a7afcce410b4 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 21 Nov 2023 18:35:51 +0000 Subject: [PATCH 19/48] update --- src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index 01fffaeca..7836e8662 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -23,7 +23,7 @@ namespace TelematicBridge DecodeJ2735Msg(msg->payload->valuestring, messageFm); string xml_payload_str = ConvertJ2735FrameToXML(messageFm); ASN_STRUCT_FREE(asn_DEF_MessageFrame, messageFm); - string json_payload_str = xml2json(xml_payload_str.c_str()); + string json_payload_str = xml2Json(xml_payload_str.c_str()); json["payload"] = StringToJson(json_payload_str); } From 71074049795b917a12d5a59d443fd22af65bc372 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 21 Nov 2023 19:13:23 +0000 Subject: [PATCH 20/48] fix register unit --- .../TelematicBridgePlugin/manifest.json | 2 +- .../src/TelematicBridgePlugin.cpp | 18 +++-- .../src/TelematicBridgePlugin.h | 1 + .../src/TelematicUnit.cpp | 69 ++++++++++--------- .../TelematicBridgePlugin/src/TelematicUnit.h | 4 +- 5 files changed, 55 insertions(+), 39 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/manifest.json b/src/v2i-hub/TelematicBridgePlugin/manifest.json index a78271c40..93f722efe 100644 --- a/src/v2i-hub/TelematicBridgePlugin/manifest.json +++ b/src/v2i-hub/TelematicBridgePlugin/manifest.json @@ -26,7 +26,7 @@ }, { "key": "NATSUrl", - "default": "nats://ec2-3-219-226-1.compute-1.amazonaws.com:4222", + "default": "nats://127.0.0.1:4222", "description": "The log level for this plugin" }, diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index 7836e8662..bbd6cb698 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -57,14 +57,24 @@ namespace TelematicBridge } } + void TelematicBridgePlugin::OnStateChange(IvpPluginState state) + { + PluginClient::OnStateChange(state); + if (state == IvpPluginState_registered) + { + UpdateConfigSettings(); + if (_telematicUnitPtr) + { + _telematicUnitPtr->connect(_natsURL, _natsConnAttempts, _natsConnTimeOut); + } + } + } + void TelematicBridgePlugin::OnConfigChanged(const char *key, const char *value) { + PLOG(logDEBUG1) << "OnConfigChanged called"; PluginClient::OnConfigChanged(key, value); UpdateConfigSettings(); - if (_telematicUnitPtr) - { - _telematicUnitPtr->connect(_natsURL, _natsConnAttempts, _natsConnTimeOut); - } } } diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h index 598e78a54..33d381b9e 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h @@ -27,6 +27,7 @@ namespace TelematicBridge public: explicit TelematicBridgePlugin(const string &name); void OnConfigChanged(const char *key, const char *value) override; + void OnStateChange(IvpPluginState state) override; void UpdateConfigSettings(); ~TelematicBridgePlugin() override = default; }; diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp index 7fed58f6f..44a3151bc 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp @@ -30,24 +30,24 @@ namespace TelematicBridge void TelematicUnit::connect(const string &natsURL, uint16_t natsConnAttempts, uint16_t natsConnTimeout) { - if (!isConnected) + // Reset connection and registration status based on the latest config update + _isConnected = false; + _isRegistered = false; + PLOG(logINFO) << "Trying to connect to " << natsURL << " attempts: " << natsConnAttempts << ", nats connect timeout: " << natsConnTimeout; + // auto s = natsConnection_Connect(&_conn, _opts); + auto s = natsConnection_ConnectTo(&_conn, natsURL.c_str()); + PLOG(logINFO) << "natsConnection_Connect returned: " << natsStatus_GetText(s); + if (s == NATS_OK) { - PLOG(logINFO) << "Trying to connect to " << natsURL << " attempts: " << natsConnAttempts << ", nats connect timeout: " << natsConnTimeout; - // auto s = natsConnection_Connect(&_conn, _opts); - auto s = natsConnection_ConnectTo(&_conn, natsURL.c_str()); - PLOG(logINFO) << "natsConnection_Connect returned: " << natsStatus_GetText(s); - if (s == NATS_OK) - { - isConnected = true; - registerUnitRequestor(); - } - else - { - isConnected = false; - nats_PrintLastErrorStack(stderr); - printf("NATS Connection Error: %u - %s\n", s, natsStatus_GetText(s)); - throw TelematicBridgeException(natsStatus_GetText(s)); - } + _isConnected = true; + registerUnitRequestor(); + } + else + { + _isConnected = false; + nats_PrintLastErrorStack(stderr); + printf("NATS Connection Error: %u - %s\n", s, natsStatus_GetText(s)); + throw TelematicBridgeException(natsStatus_GetText(s)); } } @@ -69,7 +69,7 @@ namespace TelematicBridge void TelematicUnit::registerUnitRequestor() { - while (!isRegistered) + while (!_isRegistered) { PLOG(logINFO) << "Inside register unit requestor"; natsMsg *reply = nullptr; @@ -77,8 +77,7 @@ namespace TelematicBridge auto s = natsConnection_RequestString(&reply, _conn, REGISTER_UNIT_TOPIC, payload.c_str(), TIME_OUT); if (s == NATS_OK) { - isRegistered = true; - PLOG(logINFO) << "Received regitered reply: " << natsMsg_GetData(reply); + PLOG(logINFO) << "Received registered reply: " << natsMsg_GetData(reply); Json::Value root; Json::Reader reader; bool parsingSuccessful = reader.parse(natsMsg_GetData(reply), root); @@ -86,29 +85,35 @@ namespace TelematicBridge { throw TelematicBridgeException("Error parsing the reply message"); } - if (root.isMember("location")) + + if (root.isMember("location") && root.isMember("location") && root.isMember("event_name")) { _eventLocation = root["location"].asString(); - } - if (root.isMember("location")) - { _testingType = root["testing_type"].asString(); + _eventName = root["event_name"].asString(); + + // Unit is registered when server responds with event information (location, testing_type, event_name) + _isRegistered = true; + + // Provide below services when the unit is registered + availableTopicsReplier(); + selectedTopicsReplier(); + checkStatusReplier(); } - if (root.isMember("event_name")) + else { - _eventName = root["event_name"].asString(); + _isRegistered = false; + PLOG(logERROR) << "Failed to register unit (=" << _unit.unitId << "). The unit is not registered with an active event!"; } - availableTopicsReplier(); - selectedTopicsReplier(); - checkStatusReplier(); } else { - isRegistered = false; + _isRegistered = false; nats_PrintLastErrorStack(stderr); - printf("NATS regiter Error: %u - %s\n", s, natsStatus_GetText(s)); + PLOG(logERROR) << "NATS regsiter Error: " << s << "-" << natsStatus_GetText(s); } natsMsg_Destroy(reply); + sleep(1); } } @@ -161,7 +166,7 @@ namespace TelematicBridge Json::FastWriter fasterWirter; string jsonStr = fasterWirter.write(message); auto s = natsConnection_PublishString(_conn, pubMsgTopic.c_str(), jsonStr.c_str()); - if (s != NATS_OK) + if (s == NATS_OK) { PLOG(logINFO) << "Topic: " << pubMsgTopic << ". Published: " << jsonStr; } diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h index c39d7d698..8902daa0d 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h @@ -27,8 +27,8 @@ namespace TelematicBridge public: mutex _unitMutex; mutex _availableTopicsMutex; - atomic isConnected {false}; - atomic isRegistered{false}; + atomic _isConnected {false}; + atomic _isRegistered{false}; unit_st _unit; // Global variable to store the unit information vector availableTopics; // Global variable to store available topics vector selectedTopics; // Global variable to store selected topics confirmed by users From f445eeba40574358088a0a778888bea3e9dd2cd4 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 21 Nov 2023 19:57:22 +0000 Subject: [PATCH 21/48] add exclusion list --- .../TelematicBridgePlugin/manifest.json | 26 ++++------ .../src/TelematicBridgePlugin.cpp | 5 +- .../src/TelematicBridgePlugin.h | 1 + .../src/TelematicUnit.cpp | 47 +++++-------------- .../TelematicBridgePlugin/src/TelematicUnit.h | 28 ++++++----- 5 files changed, 38 insertions(+), 69 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/manifest.json b/src/v2i-hub/TelematicBridgePlugin/manifest.json index 93f722efe..52991c070 100644 --- a/src/v2i-hub/TelematicBridgePlugin/manifest.json +++ b/src/v2i-hub/TelematicBridgePlugin/manifest.json @@ -12,29 +12,15 @@ "default": "INFO", "description": "The log level for this plugin" }, - { - "key": "NATSConnectionTimeOut", - "default": "1000", - "description": "The log level for this plugin" - - }, - { - "key": "NATSConnectionAttempts", - "default": "10", - "description": "The log level for this plugin" - - }, { "key": "NATSUrl", "default": "nats://127.0.0.1:4222", - "description": "The log level for this plugin" - + "description": "The log level for this plugin" }, { "key": "UnitId", "default": "v2xhub_id", - "description": "The log level for this plugin" - + "description": "The log level for this plugin" }, { "key": "UnitName", @@ -45,8 +31,12 @@ { "key": "UnitType", "default": "Infrastructure", - "description": "The log level for this plugin" - + "description": "The log level for this plugin" + }, + { + "key": "TopicExclusionList", + "default": "System_Alive_CommandPlugin,System_Alive_CARMAStreetsPlugin", + "description": "The list of topics are excluded from the available topic list." } ] } \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index bbd6cb698..713a0e611 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -41,12 +41,11 @@ namespace TelematicBridge void TelematicBridgePlugin::UpdateConfigSettings() { lock_guard lock(_configMutex); - GetConfigValue("NATSConnectionTimeOut", _natsConnTimeOut); - GetConfigValue("NATSConnectionAttempts", _natsConnAttempts); GetConfigValue("NATSUrl", _natsURL); GetConfigValue("UnitId", _unitId); GetConfigValue("UnitName", _unitName); GetConfigValue("UnitType", _unitType); + GetConfigValue("TopicExclusionList", _excludedTopics); unit_st unit; unit.unitId = _unitId; unit.unitName = _unitName; @@ -54,6 +53,7 @@ namespace TelematicBridge if (_telematicUnitPtr) { _telematicUnitPtr->setUnit(unit); + _telematicUnitPtr->excludedTopics = _excludedTopics; } } @@ -72,7 +72,6 @@ namespace TelematicBridge void TelematicBridgePlugin::OnConfigChanged(const char *key, const char *value) { - PLOG(logDEBUG1) << "OnConfigChanged called"; PluginClient::OnConfigChanged(key, value); UpdateConfigSettings(); } diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h index 33d381b9e..9f78c35be 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h @@ -21,6 +21,7 @@ namespace TelematicBridge string _unitType; string _unitName; string _natsURL; + string _excludedTopics; mutex _configMutex; void OnMessageReceived(IvpMessage *msg); diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp index 44a3151bc..e1d0c4ecd 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp @@ -2,41 +2,15 @@ namespace TelematicBridge { - TelematicUnit::TelematicUnit() - { - // natsStatus s; - // s = natsOptions_SetTimeout(_opts, natsConnTimeout); - // if (s == NATS_OK) - // { - // natsOptions_SetMaxReconnect(_opts, natsConnAttempts); - // } - - // if (s == NATS_OK) - // { - // s = natsOptions_SetRetryOnFailedConnect(_opts, true, nullptr, nullptr); - // } - - // if (s == NATS_OK) - // { - // s = natsOptions_SetURL(_opts, natsURL); - // } - - // if (s != NATS_OK) - // { - // nats_PrintLastErrorStack(stderr); - // throw TelematicBridgeException(natsStatus_GetText(s)); - // } - } - void TelematicUnit::connect(const string &natsURL, uint16_t natsConnAttempts, uint16_t natsConnTimeout) { - // Reset connection and registration status based on the latest config update + // Reset connection and registration status _isConnected = false; _isRegistered = false; PLOG(logINFO) << "Trying to connect to " << natsURL << " attempts: " << natsConnAttempts << ", nats connect timeout: " << natsConnTimeout; // auto s = natsConnection_Connect(&_conn, _opts); auto s = natsConnection_ConnectTo(&_conn, natsURL.c_str()); - PLOG(logINFO) << "natsConnection_Connect returned: " << natsStatus_GetText(s); + PLOG(logINFO) << "NATS connection returned: " << natsStatus_GetText(s); if (s == NATS_OK) { _isConnected = true; @@ -45,8 +19,6 @@ namespace TelematicBridge else { _isConnected = false; - nats_PrintLastErrorStack(stderr); - printf("NATS Connection Error: %u - %s\n", s, natsStatus_GetText(s)); throw TelematicBridgeException(natsStatus_GetText(s)); } } @@ -109,7 +81,6 @@ namespace TelematicBridge else { _isRegistered = false; - nats_PrintLastErrorStack(stderr); PLOG(logERROR) << "NATS regsiter Error: " << s << "-" << natsStatus_GetText(s); } natsMsg_Destroy(reply); @@ -172,7 +143,6 @@ namespace TelematicBridge } else { - nats_PrintLastErrorStack(stderr); throw TelematicBridgeException(natsStatus_GetText(s)); } } @@ -201,9 +171,12 @@ namespace TelematicBridge Json::Value topics; for (const auto &topic : obj->availableTopics) { - Json::Value topicJson; - topicJson["name"] = topic; - topics.append(topicJson); + if (!boost::icontains(obj->excludedTopics, topic)) + { + Json::Value topicJson; + topicJson["name"] = topic; + topics.append(topicJson); + } } payload["topics"] = topics; Json::FastWriter fasterWirter; @@ -231,6 +204,10 @@ namespace TelematicBridge } if (root["topics"].isArray()) { + // clear old selected topics + obj->selectedTopics.clear(); + + // update selected topics with selected topics from latest request for (auto itr = root["topics"].begin(); itr != root["topics"].end(); itr++) { obj->selectedTopics.push_back(itr->asString()); diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h index 8902daa0d..6ff2be01f 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h @@ -8,6 +8,7 @@ #include "ThreadTimer.h" #include "TelematicBridgeException.h" #include +#include using namespace std; using namespace tmx::utils; @@ -27,17 +28,18 @@ namespace TelematicBridge public: mutex _unitMutex; mutex _availableTopicsMutex; - atomic _isConnected {false}; + atomic _isConnected{false}; atomic _isRegistered{false}; - unit_st _unit; // Global variable to store the unit information - vector availableTopics; // Global variable to store available topics - vector selectedTopics; // Global variable to store selected topics confirmed by users - static CONSTEXPR const char *AVAILABLE_TOPICS = ".available_topics"; // NATS subject to pub/sub available topics - static CONSTEXPR const char *REGISTER_UNIT_TOPIC = "*.register_unit"; // NATS subject to pub/sub registering unit - static CONSTEXPR const char *PUBLISH_TOPICS = ".publish_topics"; // NATS subject to publish data stream - static CONSTEXPR const char *CHECK_STATUS = ".check_status"; // NATS subject to pub/sub checking unit status + unit_st _unit; // Global variable to store the unit information + vector availableTopics; // Global variable to store available topics + string excludedTopics; // Global variable to store topics that are excluded by the users + vector selectedTopics; // Global variable to store selected topics confirmed by users + static CONSTEXPR const char *AVAILABLE_TOPICS = ".available_topics"; // NATS subject to pub/sub available topics + static CONSTEXPR const char *REGISTER_UNIT_TOPIC = "*.register_unit"; // NATS subject to pub/sub registering unit + static CONSTEXPR const char *PUBLISH_TOPICS = ".publish_topics"; // NATS subject to publish data stream + static CONSTEXPR const char *CHECK_STATUS = ".check_status"; // NATS subject to pub/sub checking unit status unique_ptr _natsRegisterTh; - natsConnection *_conn = nullptr; // Global NATS connection object + natsConnection *_conn = nullptr; // Global NATS connection object natsOptions *_opts = nullptr; natsSubscription *subAvailableTopic = nullptr; natsSubscription *subSelectedTopic = nullptr; @@ -50,9 +52,9 @@ namespace TelematicBridge /** *@brief Construct telematic unit */ - explicit TelematicUnit(); + explicit TelematicUnit() = default; /** - * @brief A function for telematic unit to connect to NATS server. Throw exception is connection failed. * + * @brief A function for telematic unit to connect to NATS server. Throw exception is connection failed. * * @param const string NATS server URL * @param uint16_t The numbers of attempts to make connections to NATS server * @param uint16_t The timeout for between connection attempts @@ -79,8 +81,8 @@ namespace TelematicBridge * @brief Check if the given topic is inside the selectedTopics list * @param string A topic to check for existence * @return boolean indicator whether the input topic eixst. - */ - bool inSelectedTopics(const string& topic); + */ + bool inSelectedTopics(const string &topic); /** * @brief A NATS requestor for telematic unit to send register request to NATS server. From e38ff049c09f55eb9572201097b2e7620d1d13a1 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 21 Nov 2023 23:54:06 +0000 Subject: [PATCH 22/48] clean code --- .../src/TelematicBridgePlugin.cpp | 2 +- .../src/TelematicUnit.cpp | 254 ++++++++++-------- .../TelematicBridgePlugin/src/TelematicUnit.h | 123 ++++++--- 3 files changed, 223 insertions(+), 156 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index 713a0e611..9912d3158 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -53,7 +53,7 @@ namespace TelematicBridge if (_telematicUnitPtr) { _telematicUnitPtr->setUnit(unit); - _telematicUnitPtr->excludedTopics = _excludedTopics; + _telematicUnitPtr->updateExcludedTopics(_excludedTopics); } } diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp index e1d0c4ecd..0e878f348 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp @@ -4,138 +4,98 @@ namespace TelematicBridge { void TelematicUnit::connect(const string &natsURL, uint16_t natsConnAttempts, uint16_t natsConnTimeout) { - // Reset connection and registration status - _isConnected = false; - _isRegistered = false; - PLOG(logINFO) << "Trying to connect to " << natsURL << " attempts: " << natsConnAttempts << ", nats connect timeout: " << natsConnTimeout; - // auto s = natsConnection_Connect(&_conn, _opts); auto s = natsConnection_ConnectTo(&_conn, natsURL.c_str()); PLOG(logINFO) << "NATS connection returned: " << natsStatus_GetText(s); if (s == NATS_OK) { - _isConnected = true; registerUnitRequestor(); } else { - _isConnected = false; throw TelematicBridgeException(natsStatus_GetText(s)); } } - void TelematicUnit::setUnit(unit_st unit) - { - lock_guard lock(_unitMutex); - _unit = unit; - } - - void TelematicUnit::updateAvailableTopics(const string &newTopic) - { - if (find(availableTopics.begin(), availableTopics.end(), newTopic) == availableTopics.end()) - { - lock_guard lock(_availableTopicsMutex); - availableTopics.push_back(newTopic); - PLOG(logDEBUG2) << "Add topic (= " << newTopic << ") to available topics list. Size: " << availableTopics.size(); - } - } - void TelematicUnit::registerUnitRequestor() { + // Reset registration status + setRegistered(false); + while (!_isRegistered) { - PLOG(logINFO) << "Inside register unit requestor"; + PLOG(logDEBUG2) << "Inside register unit requestor"; natsMsg *reply = nullptr; string payload = "{\"unit_id\":\"" + _unit.unitId + "\"}"; auto s = natsConnection_RequestString(&reply, _conn, REGISTER_UNIT_TOPIC, payload.c_str(), TIME_OUT); if (s == NATS_OK) { - PLOG(logINFO) << "Received registered reply: " << natsMsg_GetData(reply); - Json::Value root; - Json::Reader reader; - bool parsingSuccessful = reader.parse(natsMsg_GetData(reply), root); - if (!parsingSuccessful) - { - throw TelematicBridgeException("Error parsing the reply message"); - } - - if (root.isMember("location") && root.isMember("location") && root.isMember("event_name")) + auto responseStr = natsMsg_GetData(reply); + PLOG(logINFO) << "Received registered reply: " << responseStr; + auto root = parseJson(responseStr); + if (root.isMember(LOCATION) && root.isMember(TESTING_TYPE) && root.isMember(EVENT_NAME)) { - _eventLocation = root["location"].asString(); - _testingType = root["testing_type"].asString(); - _eventName = root["event_name"].asString(); + _eventLocation = root[LOCATION].asString(); + _testingType = root[TESTING_TYPE].asString(); + _eventName = root[EVENT_NAME].asString(); // Unit is registered when server responds with event information (location, testing_type, event_name) - _isRegistered = true; - - // Provide below services when the unit is registered - availableTopicsReplier(); - selectedTopicsReplier(); - checkStatusReplier(); - } - else - { - _isRegistered = false; - PLOG(logERROR) << "Failed to register unit (=" << _unit.unitId << "). The unit is not registered with an active event!"; + setRegistered(true); } + natsMsg_Destroy(reply); } else { - _isRegistered = false; PLOG(logERROR) << "NATS regsiter Error: " << s << "-" << natsStatus_GetText(s); } - natsMsg_Destroy(reply); sleep(1); } + + if (_isRegistered) + { + // Provide below services when the unit is registered + availableTopicsReplier(); + selectedTopicsReplier(); + checkStatusReplier(); + } } void TelematicUnit::availableTopicsReplier() { - if (!subAvailableTopic) + if (!_subAvailableTopic) { PLOG(logDEBUG2) << "Inside available topic replier"; stringstream topic; topic << _unit.unitId << AVAILABLE_TOPICS; - auto s = natsConnection_Subscribe(&subAvailableTopic, _conn, topic.str().c_str(), onAvailableTopicsCallback, this); + auto s = natsConnection_Subscribe(&_subAvailableTopic, _conn, topic.str().c_str(), onAvailableTopicsCallback, this); } } void TelematicUnit::selectedTopicsReplier() { - if (!subSelectedTopic) + if (!_subSelectedTopic) { PLOG(logDEBUG2) << "Inside selected topic replier"; stringstream topic; topic << _unit.unitId << PUBLISH_TOPICS; - auto s = natsConnection_Subscribe(&subSelectedTopic, _conn, topic.str().c_str(), onSelectedTopicsCallback, this); + auto s = natsConnection_Subscribe(&_subSelectedTopic, _conn, topic.str().c_str(), onSelectedTopicsCallback, this); } } void TelematicUnit::checkStatusReplier() { - if (!subCheckStatus) + if (!_subCheckStatus) { PLOG(logDEBUG2) << "Inside check status replier"; stringstream topic; topic << _unit.unitId << CHECK_STATUS; - auto s = natsConnection_Subscribe(&subCheckStatus, _conn, topic.str().c_str(), onCheckStatusCallback, this); + auto s = natsConnection_Subscribe(&_subCheckStatus, _conn, topic.str().c_str(), onCheckStatusCallback, this); } } void TelematicUnit::publishMessage(const string &topic, const Json::Value &payload) { auto pubMsgTopic = "streets." + _unit.unitId + ".data." + topic; - Json::Value message; - message["unit_id"] = _unit.unitId; - message["unit_name"] = _unit.unitName; - message["unit_type"] = _unit.unitType; - message["location"] = _eventLocation; - message["testing_type"] = _testingType; - message["event_name"] = _eventName; - message["topic_name"] = topic; - message["timestamp"] = duration_cast(system_clock::now().time_since_epoch()).count(); - message["payload"] = payload; - Json::FastWriter fasterWirter; - string jsonStr = fasterWirter.write(message); + auto jsonStr = constructPublishedDataString(_unit, _eventLocation, _testingType, _eventName, topic, payload); auto s = natsConnection_PublishString(_conn, pubMsgTopic.c_str(), jsonStr.c_str()); if (s == NATS_OK) { @@ -147,82 +107,50 @@ namespace TelematicBridge } } - bool TelematicUnit::inSelectedTopics(const string &topic) - { - if (find(selectedTopics.begin(), selectedTopics.end(), topic) == selectedTopics.end()) - { - return false; - } - return true; - } - void TelematicUnit::onAvailableTopicsCallback(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *object) { PLOG(logDEBUG3) << "Received available topics: " << natsMsg_GetSubject(msg) << " " << natsMsg_GetData(msg); // Sends a reply - if (natsMsg_GetReply(msg) != NULL) + if (natsMsg_GetReply(msg) != nullptr) { TelematicUnit *obj = (TelematicUnit *)object; - Json::Value payload; - payload["unit_id"] = obj->_unit.unitId; - payload["unit_name"] = obj->_unit.unitName; - payload["unit_type"] = obj->_unit.unitType; - payload["timestamp"] = duration_cast(system_clock::now().time_since_epoch()).count(); - Json::Value topics; - for (const auto &topic : obj->availableTopics) - { - if (!boost::icontains(obj->excludedTopics, topic)) - { - Json::Value topicJson; - topicJson["name"] = topic; - topics.append(topicJson); - } - } - payload["topics"] = topics; - Json::FastWriter fasterWirter; - string jsonStr = fasterWirter.write(payload); - PLOG(logDEBUG2) << "Available topics replied! " << jsonStr; - natsConnection_PublishString(nc, natsMsg_GetReply(msg), jsonStr.c_str()); + auto reply = constructAvailableTopicsReplyString(obj->_unit, obj->_availableTopics, obj->_excludedTopics); + PLOG(logDEBUG3) << "Available topics replied! " << reply; + natsConnection_PublishString(nc, natsMsg_GetReply(msg), reply.c_str()); + natsMsg_Destroy(msg); } - natsMsg_Destroy(msg); } void TelematicUnit::onSelectedTopicsCallback(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *object) { PLOG(logDEBUG3) << "Received selected topics: " << natsMsg_GetSubject(msg) << " " << natsMsg_GetData(msg); // Sends a reply - if (natsMsg_GetReply(msg) != NULL) + if (natsMsg_GetReply(msg) != nullptr) { - TelematicUnit *obj = (TelematicUnit *)object; - Json::Value root; - Json::Reader reader; auto msgStr = natsMsg_GetData(msg); - bool parsingSuccessful = reader.parse(msgStr, root); - if (!parsingSuccessful) - { - throw TelematicBridgeException("Error parsing the string"); - } - if (root["topics"].isArray()) + auto root = parseJson(msgStr); + if (root.isMember(TOPICS) && root[TOPICS].isArray()) { + TelematicUnit *obj = (TelematicUnit *)object; // clear old selected topics - obj->selectedTopics.clear(); + obj->_selectedTopics.clear(); // update selected topics with selected topics from latest request - for (auto itr = root["topics"].begin(); itr != root["topics"].end(); itr++) + for (auto itr = root[TOPICS].begin(); itr != root[TOPICS].end(); itr++) { - obj->selectedTopics.push_back(itr->asString()); + obj->_selectedTopics.push_back(itr->asString()); } } - string payload = "request received!"; - PLOG(logDEBUG2) << "Selected topics replied: " << payload; - natsConnection_PublishString(nc, natsMsg_GetReply(msg), payload.c_str()); + string reply = "request received!"; + PLOG(logDEBUG3) << "Selected topics replied: " << reply; + natsConnection_PublishString(nc, natsMsg_GetReply(msg), reply.c_str()); } natsMsg_Destroy(msg); } void TelematicUnit::onCheckStatusCallback(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *object) { - if (natsMsg_GetReply(msg) != NULL) + if (natsMsg_GetReply(msg) != nullptr) { PLOG(logDEBUG3) << "Received check status msg: " << natsMsg_GetSubject(msg) << " " << natsMsg_GetData(msg); string payload = "OK"; @@ -232,10 +160,102 @@ namespace TelematicBridge } } + string TelematicUnit::constructPublishedDataString(const unit_st &unit, const string &_eventLocation, const string &_testingType, const string &_eventName, const string &topicName, const Json::Value payload) + { + Json::Value message; + message[UNIT_ID] = unit.unitId; + message[UNIT_NAME] = unit.unitName; + message[UNIT_TYPE] = unit.unitType; + message[LOCATION] = _eventLocation; + message[TESTING_TYPE] = _testingType; + message[EVENT_NAME] = _eventName; + message[TOPIC_NAME] = topicName; + message[TIMESTAMP] = duration_cast(system_clock::now().time_since_epoch()).count(); + message[PAYLOAD] = payload; + Json::FastWriter fasterWirter; + string jsonStr = fasterWirter.write(message); + } + + Json::Value TelematicUnit::parseJson(const string &jsonStr) + { + Json::Value root; + Json::Reader reader; + bool parsingSuccessful = reader.parse(jsonStr, root); + if (!parsingSuccessful) + { + throw TelematicBridgeException("Error parsing the reply message"); + } + return root; + } + + string TelematicUnit::constructAvailableTopicsReplyString(const unit_st &unit, const vector &availableTopicList, const string &excludedTopics) + { + Json::Value message; + message[UNIT_ID] = unit.unitId; + message[UNIT_NAME] = unit.unitName; + message[UNIT_TYPE] = unit.unitType; + message[TIMESTAMP] = duration_cast(system_clock::now().time_since_epoch()).count(); + Json::Value topics; + for (const auto &topic : availableTopicList) + { + if (!boost::icontains(excludedTopics, topic)) + { + Json::Value topicJson; + topicJson[NAME] = topic; + topics.append(topicJson); + } + } + message[TOPICS] = topics; + Json::FastWriter fasterWirter; + string reply = fasterWirter.write(message); + return reply; + } + + void TelematicUnit::setRegistered(bool isRegistered) + { + _isRegistered = isRegistered; + } + + void TelematicUnit::setUnit(unit_st unit) + { + lock_guard lock(_unitMutex); + _unit = unit; + } + + void TelematicUnit::updateAvailableTopics(const string &newTopic) + { + if (find(_availableTopics.begin(), _availableTopics.end(), newTopic) == _availableTopics.end()) + { + lock_guard lock(_availableTopicsMutex); + _availableTopics.push_back(newTopic); + PLOG(logINFO) << "Add topic (= " << newTopic << ") to available topics list. Size: " << _availableTopics.size(); + } + } + + void TelematicUnit::updateExcludedTopics(const string &excludedTopics) + { + lock_guard lock(_excludedTopicsMutex); + _excludedTopics = excludedTopics; + } + + bool TelematicUnit::inSelectedTopics(const string &topic) + { + if (find(_selectedTopics.begin(), _selectedTopics.end(), topic) == _selectedTopics.end()) + { + return false; + } + return true; + } + TelematicUnit::~TelematicUnit() { - natsOptions_Destroy(_opts); + natsSubscription_Destroy(_subAvailableTopic); + natsSubscription_Destroy(_subSelectedTopic); + natsSubscription_Destroy(_subCheckStatus); natsConnection_Destroy(_conn); _conn = nullptr; + _subAvailableTopic = nullptr; + _subSelectedTopic = nullptr; + _subCheckStatus = nullptr; } } \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h index 6ff2be01f..3fe78e947 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h @@ -25,30 +25,40 @@ namespace TelematicBridge class TelematicUnit { - public: + private: mutex _unitMutex; mutex _availableTopicsMutex; - atomic _isConnected{false}; - atomic _isRegistered{false}; + mutex _excludedTopicsMutex; + atomic _isRegistered{false}; // Global variable to indicate whether the unit is registered with the NATS server unit_st _unit; // Global variable to store the unit information - vector availableTopics; // Global variable to store available topics - string excludedTopics; // Global variable to store topics that are excluded by the users - vector selectedTopics; // Global variable to store selected topics confirmed by users + vector _availableTopics; // Global variable to store available topics + string _excludedTopics; // Global variable to store topics that are excluded by the users + vector _selectedTopics; // Global variable to store selected topics confirmed by users static CONSTEXPR const char *AVAILABLE_TOPICS = ".available_topics"; // NATS subject to pub/sub available topics static CONSTEXPR const char *REGISTER_UNIT_TOPIC = "*.register_unit"; // NATS subject to pub/sub registering unit static CONSTEXPR const char *PUBLISH_TOPICS = ".publish_topics"; // NATS subject to publish data stream static CONSTEXPR const char *CHECK_STATUS = ".check_status"; // NATS subject to pub/sub checking unit status - unique_ptr _natsRegisterTh; - natsConnection *_conn = nullptr; // Global NATS connection object - natsOptions *_opts = nullptr; - natsSubscription *subAvailableTopic = nullptr; - natsSubscription *subSelectedTopic = nullptr; - natsSubscription *subCheckStatus = nullptr; - int64_t TIME_OUT = 10000; - string _eventName; - string _eventLocation; - string _testingType; + natsConnection *_conn = nullptr; // Global NATS connection object + natsSubscription *_subAvailableTopic = nullptr; // Global NATS subscription object + natsSubscription *_subSelectedTopic = nullptr; // Global NATS subscription object + natsSubscription *_subCheckStatus = nullptr; // Global NATS subscription object + int64_t TIME_OUT = 10000; // NATS Connection time out in milliseconds + string _eventName; // Testing event the unit is assigned to + string _eventLocation; // Testing event location + string _testingType; // Testing type + static CONSTEXPR const char *LOCATION = "location"; // location key used to find location value from JSON + static CONSTEXPR const char *TESTING_TYPE = "testing_type"; // testing_type key used to find testing_type value from JSON + static CONSTEXPR const char *EVENT_NAME = "event_name"; // event_name key used to find event_name value from JSON + static CONSTEXPR const char *UNIT_ID = "unit_id"; // unit_id key used to find unit_id value from JSON + static CONSTEXPR const char *UNIT_NAME = "unit_name"; // unit_name key used to find unit_name value from JSON + static CONSTEXPR const char *UNIT_TYPE = "unit_type"; // unit_type key used to find unit_type value from JSON + static CONSTEXPR const char *TOPIC_NAME = "topic_name"; // topic_name key used to find topic_name value from JSON + static CONSTEXPR const char *TIMESTAMP = "timestamp"; // timestamp key used to find timestamp value from JSON + static CONSTEXPR const char *PAYLOAD = "payload"; // payload key used to find payload value from JSON + static CONSTEXPR const char *TOPICS = "topics"; // topics key used to find topics value from JSON + static CONSTEXPR const char *NAME = "name"; // topics key used to find topics value from JSON + public: /** *@brief Construct telematic unit */ @@ -62,9 +72,28 @@ namespace TelematicBridge void connect(const string &natsURL, uint16_t natsConnAttempts, uint16_t natsConnTimeout); /** - * @brief A function to update available topics global variables when discovering a new topic. + * @brief A NATS requestor for telematic unit to send register request to NATS server. + * If receives a response, it will update the isRegistered flag to indicate the unit is registered. + * If no response after the specified time out (unit of second) period, it considered register failed. + * */ + void registerUnitRequestor(); + + /** + * @brief A NATS replier to publish available topics upon receiving a request for a list of available topics. */ - void updateAvailableTopics(const string &newTopic); + void availableTopicsReplier(); + + /** + * @brief A NATS replier to subscribe to NATS server and receive requested topics from telematic server. + * Process the request and update the selectedTopics global variable. + * Respond the telematic server with acknowledgement. + */ + void selectedTopicsReplier(); + + /** + * @brief A NATS replier to publish unit status upon receiving a request for status check from telematic server. + */ + void checkStatusReplier(); /** * @brief A function to publish message stream into NATS server @@ -72,41 +101,59 @@ namespace TelematicBridge void publishMessage(const string &topic, const Json::Value &payload); /** - * @brief A function to update global unit variable - * @param unit_st object that has the unit id, type and name information + * @brief A function to parse a JSON string and create a JSON object. + * @param string input json string + * @return Json::Value */ - void setUnit(unit_st unit); + static Json::Value parseJson(const string &jsonStr); /** - * @brief Check if the given topic is inside the selectedTopics list - * @param string A topic to check for existence - * @return boolean indicator whether the input topic eixst. + * @brief construct available topic response + * @param unit_st struct that contains unit related information + * @param vector of available topics + * @param string Excluded topics separated by commas */ - bool inSelectedTopics(const string &topic); + static string constructAvailableTopicsReplyString(const unit_st &unit, const vector &availableTopicList, const string &excludedTopics); /** - * @brief A NATS requestor for telematic unit to send register request to NATS server. - * If receives a response, it will update the isRegistered flag to indicate the unit is registered. - * If no response after the specified time out (unit of second) period, it considered register failed. - * */ - void registerUnitRequestor(); + * @brief Update isregisterd indicator + */ + void setRegistered(bool isRegistered); /** - * @brief A NATS replier to publish available topics upon receiving a request for a list of available topics. + * @brief A function to update available topics global variables when discovering a new topic. */ - void availableTopicsReplier(); + void updateAvailableTopics(const string &newTopic); /** - * @brief A NATS replier to subscribe to NATS server and receive requested topics from telematic server. - * Process the request and update the selectedTopics global variable. - * Respond the telematic server with acknowledgement. + * @brief construct Json data string that will be streamed into the cloud by a publisher + * @param unit_st struct that contains unit related information + * @param string Event location + * @param string Testing type + * @param string Event name + * @param string Topic name is a combination of type_subtype_source from TMX IVPMessage + * @param string Payload is the actual data generated by V2xHub plugin */ - void selectedTopicsReplier(); + string constructPublishedDataString(const unit_st &unit, const string &_eventLocation, const string &_testingType, const string &_eventName, const string &topicName, const Json::Value payload); /** - * @brief A NATS replier to publish unit status upon receiving a request for status check from telematic server. + * @brief A function to update global unit variable + * @param unit_st object that has the unit id, type and name information */ - void checkStatusReplier(); + void setUnit(unit_st unit); + + /** + * @brief A function to update excluded topics. + * @param string Excluded topics separated by commas + */ + void updateExcludedTopics(const string &excludedTopics); + + /** + * @brief Check if the given topic is inside the selectedTopics list + * @param string A topic to check for existence + * @return boolean indicator whether the input topic eixst. + */ + bool inSelectedTopics(const string &topic); static void onAvailableTopicsCallback(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *object); static void onSelectedTopicsCallback(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *object); From c72ecc975a295e7ddb7af17584a342412b38528b Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 22 Nov 2023 00:05:06 +0000 Subject: [PATCH 23/48] resolve conflict --- src/v2i-hub/TelematicBridgePlugin/manifest.json | 3 +-- .../TelematicBridgePlugin/src/TelematicBridgePlugin.cpp | 5 +---- src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp | 2 +- src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h | 4 +--- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/manifest.json b/src/v2i-hub/TelematicBridgePlugin/manifest.json index 52991c070..638f52528 100644 --- a/src/v2i-hub/TelematicBridgePlugin/manifest.json +++ b/src/v2i-hub/TelematicBridgePlugin/manifest.json @@ -25,8 +25,7 @@ { "key": "UnitName", "default": "East Intersection", - "description": "The log level for this plugin" - + "description": "The log level for this plugin" }, { "key": "UnitType", diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index 047c6f06d..203f8f92c 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -4,11 +4,8 @@ namespace TelematicBridge { TelematicBridgePlugin::TelematicBridgePlugin(const string &name) : PluginClient(name) { -<<<<<<< HEAD _telematicUnitPtr = make_shared(); UpdateConfigSettings(); -======= ->>>>>>> develop AddMessageFilter("*", "*", IvpMsgFlags_None); AddMessageFilter("J2735", "*", IvpMsgFlags_RouteDSRC); SubscribeToMessages(); @@ -68,7 +65,7 @@ namespace TelematicBridge UpdateConfigSettings(); if (_telematicUnitPtr) { - _telematicUnitPtr->connect(_natsURL, _natsConnAttempts, _natsConnTimeOut); + _telematicUnitPtr->connect(_natsURL); } } } diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp index 0e878f348..49a471ff1 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp @@ -2,7 +2,7 @@ namespace TelematicBridge { - void TelematicUnit::connect(const string &natsURL, uint16_t natsConnAttempts, uint16_t natsConnTimeout) + void TelematicUnit::connect(const string &natsURL) { auto s = natsConnection_ConnectTo(&_conn, natsURL.c_str()); PLOG(logINFO) << "NATS connection returned: " << natsStatus_GetText(s); diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h index 3fe78e947..a69bde47d 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h @@ -66,10 +66,8 @@ namespace TelematicBridge /** * @brief A function for telematic unit to connect to NATS server. Throw exception is connection failed. * * @param const string NATS server URL - * @param uint16_t The numbers of attempts to make connections to NATS server - * @param uint16_t The timeout for between connection attempts */ - void connect(const string &natsURL, uint16_t natsConnAttempts, uint16_t natsConnTimeout); + void connect(const string &natsURL); /** * @brief A NATS requestor for telematic unit to send register request to NATS server. From 383bafd54c4ed6629ce88802ffda43d9c3be375c Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 22 Nov 2023 15:19:21 +0000 Subject: [PATCH 24/48] add unit test --- .../TelematicBridgePlugin/CMakeLists.txt | 4 +- .../src/TelematicUnit.cpp | 45 ++++--- .../TelematicBridgePlugin/src/TelematicUnit.h | 30 +++-- .../test/test_TelematicUnit.cpp | 117 ++++++++++++++++++ 4 files changed, 161 insertions(+), 35 deletions(-) create mode 100644 src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp diff --git a/src/v2i-hub/TelematicBridgePlugin/CMakeLists.txt b/src/v2i-hub/TelematicBridgePlugin/CMakeLists.txt index 6e0a0e260..df7b1c0f7 100644 --- a/src/v2i-hub/TelematicBridgePlugin/CMakeLists.txt +++ b/src/v2i-hub/TelematicBridgePlugin/CMakeLists.txt @@ -8,8 +8,10 @@ TARGET_LINK_LIBRARIES ( ${PROJECT_NAME} tmxutils jsoncpp nats) #################################################### ################## Testing ####################### #################################################### +add_library(${PROJECT_NAME}_lib src/TelematicUnit.cpp) +target_link_libraries(${PROJECT_NAME}_lib PUBLIC tmxutils jsoncpp nats) enable_testing() include_directories(${PROJECT_SOURCE_DIR}/src) file(GLOB_RECURSE TEST_SOURCES LIST_DIRECTORIES false test/*.h test/*.cpp) add_executable(${PROJECT_NAME}_test ${TEST_SOURCES}) -target_link_libraries(${PROJECT_NAME}_test PRIVATE gtest tmxutils jsoncpp nats) \ No newline at end of file +target_link_libraries(${PROJECT_NAME}_test PRIVATE gtest ${PROJECT_NAME}_lib) \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp index 49a471ff1..29a026570 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp @@ -19,7 +19,7 @@ namespace TelematicBridge void TelematicUnit::registerUnitRequestor() { // Reset registration status - setRegistered(false); + _isRegistered = false; while (!_isRegistered) { @@ -39,13 +39,13 @@ namespace TelematicBridge _eventName = root[EVENT_NAME].asString(); // Unit is registered when server responds with event information (location, testing_type, event_name) - setRegistered(true); + _isRegistered = true; } natsMsg_Destroy(reply); } else { - PLOG(logERROR) << "NATS regsiter Error: " << s << "-" << natsStatus_GetText(s); + throw TelematicBridgeException(natsStatus_GetText(s)); } sleep(1); } @@ -66,7 +66,7 @@ namespace TelematicBridge PLOG(logDEBUG2) << "Inside available topic replier"; stringstream topic; topic << _unit.unitId << AVAILABLE_TOPICS; - auto s = natsConnection_Subscribe(&_subAvailableTopic, _conn, topic.str().c_str(), onAvailableTopicsCallback, this); + natsConnection_Subscribe(&_subAvailableTopic, _conn, topic.str().c_str(), onAvailableTopicsCallback, this); } } @@ -77,7 +77,7 @@ namespace TelematicBridge PLOG(logDEBUG2) << "Inside selected topic replier"; stringstream topic; topic << _unit.unitId << PUBLISH_TOPICS; - auto s = natsConnection_Subscribe(&_subSelectedTopic, _conn, topic.str().c_str(), onSelectedTopicsCallback, this); + natsConnection_Subscribe(&_subSelectedTopic, _conn, topic.str().c_str(), onSelectedTopicsCallback, this); } } @@ -88,7 +88,7 @@ namespace TelematicBridge PLOG(logDEBUG2) << "Inside check status replier"; stringstream topic; topic << _unit.unitId << CHECK_STATUS; - auto s = natsConnection_Subscribe(&_subCheckStatus, _conn, topic.str().c_str(), onCheckStatusCallback, this); + natsConnection_Subscribe(&_subCheckStatus, _conn, topic.str().c_str(), onCheckStatusCallback, this); } } @@ -113,10 +113,13 @@ namespace TelematicBridge // Sends a reply if (natsMsg_GetReply(msg) != nullptr) { - TelematicUnit *obj = (TelematicUnit *)object; - auto reply = constructAvailableTopicsReplyString(obj->_unit, obj->_availableTopics, obj->_excludedTopics); - PLOG(logDEBUG3) << "Available topics replied! " << reply; - natsConnection_PublishString(nc, natsMsg_GetReply(msg), reply.c_str()); + const auto obj = (TelematicUnit *)object; + if (obj) + { + auto reply = constructAvailableTopicsReplyString(obj->_unit, obj->_availableTopics, obj->_excludedTopics); + PLOG(logDEBUG3) << "Available topics replied! " << reply; + natsConnection_PublishString(nc, natsMsg_GetReply(msg), reply.c_str()); + } natsMsg_Destroy(msg); } } @@ -131,7 +134,7 @@ namespace TelematicBridge auto root = parseJson(msgStr); if (root.isMember(TOPICS) && root[TOPICS].isArray()) { - TelematicUnit *obj = (TelematicUnit *)object; + auto obj = (TelematicUnit *)object; // clear old selected topics obj->_selectedTopics.clear(); @@ -144,8 +147,8 @@ namespace TelematicBridge string reply = "request received!"; PLOG(logDEBUG3) << "Selected topics replied: " << reply; natsConnection_PublishString(nc, natsMsg_GetReply(msg), reply.c_str()); + natsMsg_Destroy(msg); } - natsMsg_Destroy(msg); } void TelematicUnit::onCheckStatusCallback(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *object) @@ -160,20 +163,21 @@ namespace TelematicBridge } } - string TelematicUnit::constructPublishedDataString(const unit_st &unit, const string &_eventLocation, const string &_testingType, const string &_eventName, const string &topicName, const Json::Value payload) + string TelematicUnit::constructPublishedDataString(const unit_st &unit, const string &eventLocation, const string &testingType, const string &eventName, const string &topicName, const Json::Value& payload) const { Json::Value message; message[UNIT_ID] = unit.unitId; message[UNIT_NAME] = unit.unitName; message[UNIT_TYPE] = unit.unitType; - message[LOCATION] = _eventLocation; - message[TESTING_TYPE] = _testingType; - message[EVENT_NAME] = _eventName; + message[LOCATION] = eventLocation; + message[TESTING_TYPE] = testingType; + message[EVENT_NAME] = eventName; message[TOPIC_NAME] = topicName; - message[TIMESTAMP] = duration_cast(system_clock::now().time_since_epoch()).count(); + message[TIMESTAMP] = payload.isMember("timestamp") ? payload["timestamp"].asUInt64() : duration_cast(system_clock::now().time_since_epoch()).count(); message[PAYLOAD] = payload; Json::FastWriter fasterWirter; string jsonStr = fasterWirter.write(message); + return jsonStr; } Json::Value TelematicUnit::parseJson(const string &jsonStr) @@ -211,12 +215,7 @@ namespace TelematicBridge return reply; } - void TelematicUnit::setRegistered(bool isRegistered) - { - _isRegistered = isRegistered; - } - - void TelematicUnit::setUnit(unit_st unit) + void TelematicUnit::setUnit(const unit_st& unit) { lock_guard lock(_unitMutex); _unit = unit; diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h index a69bde47d..4ed37b517 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h @@ -65,7 +65,7 @@ namespace TelematicBridge explicit TelematicUnit() = default; /** * @brief A function for telematic unit to connect to NATS server. Throw exception is connection failed. * - * @param const string NATS server URL + * @param string string NATS server URL */ void connect(const string &natsURL); @@ -77,7 +77,8 @@ namespace TelematicBridge void registerUnitRequestor(); /** - * @brief A NATS replier to publish available topics upon receiving a request for a list of available topics. + * @brief A NATS replier to subscribe to NATS server and receive available topics request. + * Publish list of available topics after receiving/processing the request. */ void availableTopicsReplier(); @@ -89,7 +90,8 @@ namespace TelematicBridge void selectedTopicsReplier(); /** - * @brief A NATS replier to publish unit status upon receiving a request for status check from telematic server. + * @brief A NATS replier to subscribe to NATS server and receive request for status check from telematic server. + * Publish unit status upon receiving a request. */ void checkStatusReplier(); @@ -113,11 +115,6 @@ namespace TelematicBridge */ static string constructAvailableTopicsReplyString(const unit_st &unit, const vector &availableTopicList, const string &excludedTopics); - /** - * @brief Update isregisterd indicator - */ - void setRegistered(bool isRegistered); - /** * @brief A function to update available topics global variables when discovering a new topic. */ @@ -130,15 +127,15 @@ namespace TelematicBridge * @param string Testing type * @param string Event name * @param string Topic name is a combination of type_subtype_source from TMX IVPMessage - * @param string Payload is the actual data generated by V2xHub plugin + * @param Json::Value Payload is the actual data generated by V2xHub plugin */ - string constructPublishedDataString(const unit_st &unit, const string &_eventLocation, const string &_testingType, const string &_eventName, const string &topicName, const Json::Value payload); + string constructPublishedDataString(const unit_st &unit, const string &eventLocation, const string &testingType, const string &eventName, const string &topicName, const Json::Value& payload) const; /** * @brief A function to update global unit variable * @param unit_st object that has the unit id, type and name information */ - void setUnit(unit_st unit); + void setUnit(const unit_st& unit); /** * @brief A function to update excluded topics. @@ -153,8 +150,19 @@ namespace TelematicBridge */ bool inSelectedTopics(const string &topic); + /** + * @brief A callback function for available topic replier + */ static void onAvailableTopicsCallback(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *object); + + /** + * @brief A callback function for selected topic replier + */ static void onSelectedTopicsCallback(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *object); + + /** + * @brief A callback function for check status replier + */ static void onCheckStatusCallback(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *object); ~TelematicUnit(); diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp new file mode 100644 index 000000000..20708f336 --- /dev/null +++ b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp @@ -0,0 +1,117 @@ +#include +#include "TelematicUnit.h" + +namespace TelematicBridge +{ + class test_TelematicUnit : public ::testing::Test + { + public: + shared_ptr _telematicUnitPtr = make_shared(); + unit_st unit = + { + "test_id", + "test_name", + "infrastructure"}; + }; + + TEST_F(test_TelematicUnit, setUnit) + { + ASSERT_NO_THROW(_telematicUnitPtr->setUnit(unit)); + } + + TEST_F(test_TelematicUnit, updateExcludedTopics) + { + ASSERT_NO_THROW(_telematicUnitPtr->updateExcludedTopics("test_topic")); + } + + TEST_F(test_TelematicUnit, inSelectedTopics) + { + ASSERT_FALSE(_telematicUnitPtr->inSelectedTopics("test_topic")); + } + + TEST_F(test_TelematicUnit, updateAvailableTopics) + { + ASSERT_NO_THROW(_telematicUnitPtr->updateAvailableTopics("test_topic")); + } + + TEST_F(test_TelematicUnit, constructAvailableTopicsReplyString) + { + vector topics = {"test_topic", "excluded_topic"}; + string excluded_topic = "excluded_topic"; + auto reply = TelematicUnit::constructAvailableTopicsReplyString(unit, topics, excluded_topic); + auto json = TelematicUnit::parseJson(reply); + ASSERT_EQ("test_topic", json["topics"][0]["name"].asString()); + } + + TEST_F(test_TelematicUnit, constructPublishedDataString) + { + string eventLocation = "location"; + string testingType = "unit_test"; + string eventName = "testing"; + string topicName = "test_topic"; + Json::Value payload; + payload["body"] = "test_body"; + auto reply = _telematicUnitPtr->constructPublishedDataString(unit, eventLocation, testingType, eventName, topicName, payload); + auto json = TelematicUnit::parseJson(reply); + ASSERT_EQ(eventLocation, json["location"].asString()); + ASSERT_EQ(testingType, json["testing_type"].asString()); + ASSERT_EQ(eventName, json["event_name"].asString()); + } + + TEST_F(test_TelematicUnit, onCheckStatusCallback) + { + natsMsg *msg; + string data = "{\"data\":\"test\"}"; + natsMsg_Create(&msg, "test_subject", "Test_reply", data.c_str(), data.size()); + ASSERT_NO_THROW(TelematicUnit::onCheckStatusCallback(nullptr, nullptr, msg, nullptr)); + } + + TEST_F(test_TelematicUnit, onSelectedTopicsCallback) + { + natsMsg *msg; + string data = "{\"data\":\"test\"}"; + natsMsg_Create(&msg, "test_subject", "Test_reply", data.c_str(), data.size()); + ASSERT_NO_THROW(TelematicUnit::onSelectedTopicsCallback(nullptr, nullptr, msg, nullptr)); + } + + TEST_F(test_TelematicUnit, onAvailableTopicsCallback) + { + natsMsg *msg; + string data = "{\"data\":\"test\"}"; + natsMsg_Create(&msg, "test_subject", "Test_reply", data.c_str(), data.size()); + ASSERT_NO_THROW(TelematicUnit::onAvailableTopicsCallback(nullptr, nullptr, msg, _telematicUnitPtr.get())); + } + + TEST_F(test_TelematicUnit, publishMessage) + { + string topicName = "test_topic"; + Json::Value payload; + payload["body"] = "test_body"; + ASSERT_THROW(_telematicUnitPtr->publishMessage(topicName, payload), TelematicBridgeException); + } + + TEST_F(test_TelematicUnit, checkStatusReplier) + { + _telematicUnitPtr->checkStatusReplier(); + } + + TEST_F(test_TelematicUnit, selectedTopicsReplier) + { + _telematicUnitPtr->selectedTopicsReplier(); + } + + TEST_F(test_TelematicUnit, availableTopicsReplier) + { + _telematicUnitPtr->availableTopicsReplier(); + } + + TEST_F(test_TelematicUnit, registerUnitRequestor) + { + ASSERT_THROW(_telematicUnitPtr->registerUnitRequestor(), TelematicBridgeException); + } + + TEST_F(test_TelematicUnit, connect) + { + ASSERT_THROW(_telematicUnitPtr->connect("nats://127.0.0.1:4222"), TelematicBridgeException); + } +} \ No newline at end of file From 758a8eaa8528cd753b24e5112caf62bce16dac7b Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 22 Nov 2023 15:53:30 +0000 Subject: [PATCH 25/48] update unit test --- .../src/TelematicUnit.cpp | 75 ++++++++++++++----- .../TelematicBridgePlugin/src/TelematicUnit.h | 48 +++++++++++- .../test/test_TelematicUnit.cpp | 29 +++++-- 3 files changed, 125 insertions(+), 27 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp index 29a026570..07ca1bb29 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp @@ -116,9 +116,9 @@ namespace TelematicBridge const auto obj = (TelematicUnit *)object; if (obj) { - auto reply = constructAvailableTopicsReplyString(obj->_unit, obj->_availableTopics, obj->_excludedTopics); - PLOG(logDEBUG3) << "Available topics replied! " << reply; + auto reply = constructAvailableTopicsReplyString(obj->getUnit(), obj->getEventLocation(), obj->getTestingType(), obj->getEventName(), obj->getAvailableTopics(), obj->getExcludedTopics()); natsConnection_PublishString(nc, natsMsg_GetReply(msg), reply.c_str()); + PLOG(logDEBUG3) << "Available topics replied! " << reply; } natsMsg_Destroy(msg); } @@ -136,17 +136,17 @@ namespace TelematicBridge { auto obj = (TelematicUnit *)object; // clear old selected topics - obj->_selectedTopics.clear(); + obj->clearSelectedTopics(); // update selected topics with selected topics from latest request for (auto itr = root[TOPICS].begin(); itr != root[TOPICS].end(); itr++) { - obj->_selectedTopics.push_back(itr->asString()); + obj->addSelectedTopic(itr->asString()); } } string reply = "request received!"; - PLOG(logDEBUG3) << "Selected topics replied: " << reply; natsConnection_PublishString(nc, natsMsg_GetReply(msg), reply.c_str()); + PLOG(logDEBUG3) << "Selected topics replied: " << reply; natsMsg_Destroy(msg); } } @@ -155,15 +155,13 @@ namespace TelematicBridge { if (natsMsg_GetReply(msg) != nullptr) { - PLOG(logDEBUG3) << "Received check status msg: " << natsMsg_GetSubject(msg) << " " << natsMsg_GetData(msg); - string payload = "OK"; - PLOG(logDEBUG3) << "Status Check: " << payload; - natsConnection_PublishString(nc, natsMsg_GetReply(msg), payload.c_str()); + natsConnection_PublishString(nc, natsMsg_GetReply(msg), "OK"); + PLOG(logDEBUG3) << "Received check status msg: " << natsMsg_GetSubject(msg) << " " << natsMsg_GetData(msg) << ". Replied: OK"; natsMsg_Destroy(msg); } } - string TelematicUnit::constructPublishedDataString(const unit_st &unit, const string &eventLocation, const string &testingType, const string &eventName, const string &topicName, const Json::Value& payload) const + string TelematicUnit::constructPublishedDataString(const unit_st &unit, const string &eventLocation, const string &testingType, const string &eventName, const string &topicName, const Json::Value &payload) const { Json::Value message; message[UNIT_ID] = unit.unitId; @@ -192,12 +190,15 @@ namespace TelematicBridge return root; } - string TelematicUnit::constructAvailableTopicsReplyString(const unit_st &unit, const vector &availableTopicList, const string &excludedTopics) + string TelematicUnit::constructAvailableTopicsReplyString(const unit_st &unit, const string &eventLocation, const string &testingType, const string &eventName, const vector &availableTopicList, const string &excludedTopics) { Json::Value message; message[UNIT_ID] = unit.unitId; message[UNIT_NAME] = unit.unitName; message[UNIT_TYPE] = unit.unitType; + message[LOCATION] = eventLocation; + message[TESTING_TYPE] = testingType; + message[EVENT_NAME] = eventName; message[TIMESTAMP] = duration_cast(system_clock::now().time_since_epoch()).count(); Json::Value topics; for (const auto &topic : availableTopicList) @@ -215,12 +216,6 @@ namespace TelematicBridge return reply; } - void TelematicUnit::setUnit(const unit_st& unit) - { - lock_guard lock(_unitMutex); - _unit = unit; - } - void TelematicUnit::updateAvailableTopics(const string &newTopic) { if (find(_availableTopics.begin(), _availableTopics.end(), newTopic) == _availableTopics.end()) @@ -246,6 +241,52 @@ namespace TelematicBridge return true; } + void TelematicUnit::setUnit(const unit_st &unit) + { + lock_guard lock(_unitMutex); + _unit = unit; + } + + unit_st TelematicUnit::getUnit() const + { + return _unit; + } + + string TelematicUnit::getEventName() const + { + return _eventName; + } + + string TelematicUnit::getEventLocation() const + { + return _eventLocation; + } + + string TelematicUnit::getTestingType() const + { + return _testingType; + } + + vector TelematicUnit::getAvailableTopics() const + { + return _availableTopics; + } + + string TelematicUnit::getExcludedTopics() const + { + return _excludedTopics; + } + + void TelematicUnit::addSelectedTopic(const string &newSelectedTopic) + { + _selectedTopics.push_back(newSelectedTopic); + } + + void TelematicUnit::clearSelectedTopics() + { + _selectedTopics.clear(); + } + TelematicUnit::~TelematicUnit() { natsSubscription_Destroy(_subAvailableTopic); diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h index 4ed37b517..148db8dcd 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h @@ -113,7 +113,7 @@ namespace TelematicBridge * @param vector of available topics * @param string Excluded topics separated by commas */ - static string constructAvailableTopicsReplyString(const unit_st &unit, const vector &availableTopicList, const string &excludedTopics); + static string constructAvailableTopicsReplyString(const unit_st &unit, const string &eventLocation, const string &testingType, const string &eventName, const vector &availableTopicList, const string &excludedTopics); /** * @brief A function to update available topics global variables when discovering a new topic. @@ -129,13 +129,53 @@ namespace TelematicBridge * @param string Topic name is a combination of type_subtype_source from TMX IVPMessage * @param Json::Value Payload is the actual data generated by V2xHub plugin */ - string constructPublishedDataString(const unit_st &unit, const string &eventLocation, const string &testingType, const string &eventName, const string &topicName, const Json::Value& payload) const; + string constructPublishedDataString(const unit_st &unit, const string &eventLocation, const string &testingType, const string &eventName, const string &topicName, const Json::Value &payload) const; /** * @brief A function to update global unit variable * @param unit_st object that has the unit id, type and name information */ - void setUnit(const unit_st& unit); + void setUnit(const unit_st &unit); + + /** + * @brief Return unit structure + */ + unit_st getUnit() const; + + /** + * @brief Return list of available topics + */ + vector getAvailableTopics() const; + + /** + * @brief Return excluded topics string. + */ + string getExcludedTopics() const; + + /** + * @brief Return event name + */ + string getEventName() const; + + /** + * @brief Return event location + */ + string getEventLocation() const; + + /** + * @brief Return testing type + */ + string getTestingType() const; + + /** + * @brief Add new selected topic into the selected topics list + */ + void addSelectedTopic(const string &newSelectedTopic); + + /** + * @brief Clear selected topics list + */ + void clearSelectedTopics(); /** * @brief A function to update excluded topics. @@ -154,7 +194,7 @@ namespace TelematicBridge * @brief A callback function for available topic replier */ static void onAvailableTopicsCallback(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *object); - + /** * @brief A callback function for selected topic replier */ diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp index 20708f336..cd92253c8 100644 --- a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp @@ -17,6 +17,7 @@ namespace TelematicBridge TEST_F(test_TelematicUnit, setUnit) { ASSERT_NO_THROW(_telematicUnitPtr->setUnit(unit)); + ASSERT_EQ(unit.unitId, _telematicUnitPtr->getUnit().unitId); } TEST_F(test_TelematicUnit, updateExcludedTopics) @@ -24,11 +25,6 @@ namespace TelematicBridge ASSERT_NO_THROW(_telematicUnitPtr->updateExcludedTopics("test_topic")); } - TEST_F(test_TelematicUnit, inSelectedTopics) - { - ASSERT_FALSE(_telematicUnitPtr->inSelectedTopics("test_topic")); - } - TEST_F(test_TelematicUnit, updateAvailableTopics) { ASSERT_NO_THROW(_telematicUnitPtr->updateAvailableTopics("test_topic")); @@ -38,7 +34,10 @@ namespace TelematicBridge { vector topics = {"test_topic", "excluded_topic"}; string excluded_topic = "excluded_topic"; - auto reply = TelematicUnit::constructAvailableTopicsReplyString(unit, topics, excluded_topic); + string eventLocation = "location"; + string testingType = "unit_test"; + string eventName = "testing"; + auto reply = TelematicUnit::constructAvailableTopicsReplyString(unit, eventLocation, testingType, eventName, topics, excluded_topic); auto json = TelematicUnit::parseJson(reply); ASSERT_EQ("test_topic", json["topics"][0]["name"].asString()); } @@ -114,4 +113,22 @@ namespace TelematicBridge { ASSERT_THROW(_telematicUnitPtr->connect("nats://127.0.0.1:4222"), TelematicBridgeException); } + + TEST_F(test_TelematicUnit, getters) + { + ASSERT_EQ(0, _telematicUnitPtr->getAvailableTopics().size()); + ASSERT_EQ("", _telematicUnitPtr->getEventLocation()); + ASSERT_EQ("", _telematicUnitPtr->getEventName()); + ASSERT_EQ("", _telematicUnitPtr->getExcludedTopics()); + ASSERT_EQ("", _telematicUnitPtr->getTestingType()); + } + + TEST_F(test_TelematicUnit, selectedTopics) + { + string selectedTopic = "test_selected_topics"; + _telematicUnitPtr->addSelectedTopic(selectedTopic); + ASSERT_TRUE(_telematicUnitPtr->inSelectedTopics(selectedTopic)); + _telematicUnitPtr->clearSelectedTopics(); + ASSERT_FALSE(_telematicUnitPtr->inSelectedTopics(selectedTopic)); + } } \ No newline at end of file From 6175f1ff92ceb9d9c958bb3a20ba2de08b1368b2 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 22 Nov 2023 16:08:58 +0000 Subject: [PATCH 26/48] code coverage --- .../TelematicBridgePlugin/src/TelematicUnit.cpp | 13 +++++-------- .../test/test_TelematicUnit.cpp | 4 ++-- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp index 07ca1bb29..fe12b116f 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp @@ -111,15 +111,12 @@ namespace TelematicBridge { PLOG(logDEBUG3) << "Received available topics: " << natsMsg_GetSubject(msg) << " " << natsMsg_GetData(msg); // Sends a reply - if (natsMsg_GetReply(msg) != nullptr) + if (object && natsMsg_GetReply(msg) != nullptr) { const auto obj = (TelematicUnit *)object; - if (obj) - { - auto reply = constructAvailableTopicsReplyString(obj->getUnit(), obj->getEventLocation(), obj->getTestingType(), obj->getEventName(), obj->getAvailableTopics(), obj->getExcludedTopics()); - natsConnection_PublishString(nc, natsMsg_GetReply(msg), reply.c_str()); - PLOG(logDEBUG3) << "Available topics replied! " << reply; - } + auto reply = constructAvailableTopicsReplyString(obj->getUnit(), obj->getEventLocation(), obj->getTestingType(), obj->getEventName(), obj->getAvailableTopics(), obj->getExcludedTopics()); + natsConnection_PublishString(nc, natsMsg_GetReply(msg), reply.c_str()); + PLOG(logDEBUG3) << "Available topics replied! " << reply; natsMsg_Destroy(msg); } } @@ -132,7 +129,7 @@ namespace TelematicBridge { auto msgStr = natsMsg_GetData(msg); auto root = parseJson(msgStr); - if (root.isMember(TOPICS) && root[TOPICS].isArray()) + if (object && root.isMember(TOPICS) && root[TOPICS].isArray()) { auto obj = (TelematicUnit *)object; // clear old selected topics diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp index cd92253c8..cc75a7bea 100644 --- a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp @@ -68,9 +68,9 @@ namespace TelematicBridge TEST_F(test_TelematicUnit, onSelectedTopicsCallback) { natsMsg *msg; - string data = "{\"data\":\"test\"}"; + string data = "{\"topics\":\"test_topic\"}"; natsMsg_Create(&msg, "test_subject", "Test_reply", data.c_str(), data.size()); - ASSERT_NO_THROW(TelematicUnit::onSelectedTopicsCallback(nullptr, nullptr, msg, nullptr)); + ASSERT_NO_THROW(TelematicUnit::onSelectedTopicsCallback(nullptr, nullptr, msg, _telematicUnitPtr.get())); } TEST_F(test_TelematicUnit, onAvailableTopicsCallback) From d3936df8836606671483f3112b47df842e0b08ed Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 22 Nov 2023 16:49:27 +0000 Subject: [PATCH 27/48] code coverage --- .../TelematicBridgePlugin/src/TelematicBridgePlugin.cpp | 5 +---- src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h | 2 +- .../TelematicBridgePlugin/test/test_TelematicUnit.cpp | 4 +++- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index 203f8f92c..a010c3b2f 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -46,10 +46,7 @@ namespace TelematicBridge GetConfigValue("UnitName", _unitName); GetConfigValue("UnitType", _unitType); GetConfigValue("TopicExclusionList", _excludedTopics); - unit_st unit; - unit.unitId = _unitId; - unit.unitName = _unitName; - unit.unitType = _unitType; + unit_st unit = {_unitId, _unitName, _unitType}; if (_telematicUnitPtr) { _telematicUnitPtr->setUnit(unit); diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h index 148db8dcd..da1e8e455 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h @@ -19,8 +19,8 @@ namespace TelematicBridge using unit_st = struct unit { string unitId; // Unique identifier for each unit - string unitType; // Unit categorized base on unit type: platform or infrastructure string unitName; // Descriptive name for each unit + string unitType; // Unit categorized base on unit type: platform or infrastructure }; class TelematicUnit diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp index cc75a7bea..d93cf96f8 100644 --- a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp @@ -55,6 +55,7 @@ namespace TelematicBridge ASSERT_EQ(eventLocation, json["location"].asString()); ASSERT_EQ(testingType, json["testing_type"].asString()); ASSERT_EQ(eventName, json["event_name"].asString()); + ASSERT_THROW(TelematicUnit::parseJson("Invalid Json"), TelematicBridgeException); } TEST_F(test_TelematicUnit, onCheckStatusCallback) @@ -68,9 +69,10 @@ namespace TelematicBridge TEST_F(test_TelematicUnit, onSelectedTopicsCallback) { natsMsg *msg; - string data = "{\"topics\":\"test_topic\"}"; + string data = "{\"topics\":[\"test_topic\"]}"; natsMsg_Create(&msg, "test_subject", "Test_reply", data.c_str(), data.size()); ASSERT_NO_THROW(TelematicUnit::onSelectedTopicsCallback(nullptr, nullptr, msg, _telematicUnitPtr.get())); + ASSERT_TRUE(_telematicUnitPtr->inSelectedTopics("test_topic")); } TEST_F(test_TelematicUnit, onAvailableTopicsCallback) From 4370816b5a8eae44d8ca82513fe5852a369cc0bd Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 22 Nov 2023 17:06:09 +0000 Subject: [PATCH 28/48] code coverage --- .../TelematicBridgePlugin/manifest.json | 2 +- .../src/TelematicUnit.cpp | 21 +++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/manifest.json b/src/v2i-hub/TelematicBridgePlugin/manifest.json index 638f52528..e150205c7 100644 --- a/src/v2i-hub/TelematicBridgePlugin/manifest.json +++ b/src/v2i-hub/TelematicBridgePlugin/manifest.json @@ -34,7 +34,7 @@ }, { "key": "TopicExclusionList", - "default": "System_Alive_CommandPlugin,System_Alive_CARMAStreetsPlugin", + "default": "System_KeepAlive_CommandPlugin,System_KeepAlive_CARMAStreetsPlugin,System_KeepAlive_CDASimAdapter,System_KeepAlive_MessageReceiver", "description": "The list of topics are excluded from the available topic list." } ] diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp index fe12b116f..e9ed23a33 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp @@ -115,9 +115,12 @@ namespace TelematicBridge { const auto obj = (TelematicUnit *)object; auto reply = constructAvailableTopicsReplyString(obj->getUnit(), obj->getEventLocation(), obj->getTestingType(), obj->getEventName(), obj->getAvailableTopics(), obj->getExcludedTopics()); - natsConnection_PublishString(nc, natsMsg_GetReply(msg), reply.c_str()); - PLOG(logDEBUG3) << "Available topics replied! " << reply; + auto s = natsConnection_PublishString(nc, natsMsg_GetReply(msg), reply.c_str()); natsMsg_Destroy(msg); + if (s == NATS_OK) + { + PLOG(logDEBUG3) << "Available topics replied: " << reply; + } } } @@ -142,9 +145,12 @@ namespace TelematicBridge } } string reply = "request received!"; - natsConnection_PublishString(nc, natsMsg_GetReply(msg), reply.c_str()); - PLOG(logDEBUG3) << "Selected topics replied: " << reply; + auto s = natsConnection_PublishString(nc, natsMsg_GetReply(msg), reply.c_str()); natsMsg_Destroy(msg); + if (s == NATS_OK) + { + PLOG(logDEBUG3) << "Selected topics replied: " << reply; + } } } @@ -152,8 +158,11 @@ namespace TelematicBridge { if (natsMsg_GetReply(msg) != nullptr) { - natsConnection_PublishString(nc, natsMsg_GetReply(msg), "OK"); - PLOG(logDEBUG3) << "Received check status msg: " << natsMsg_GetSubject(msg) << " " << natsMsg_GetData(msg) << ". Replied: OK"; + auto s = natsConnection_PublishString(nc, natsMsg_GetReply(msg), "OK"); + if (s == NATS_OK) + { + PLOG(logDEBUG3) << "Received check status msg: " << natsMsg_GetSubject(msg) << " " << natsMsg_GetData(msg) << ". Replied: OK"; + } natsMsg_Destroy(msg); } } From 2d6364a717c02b5b7b839add89ddf11405e16276 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 22 Nov 2023 17:49:43 +0000 Subject: [PATCH 29/48] code coverage --- .../src/TelematicUnit.cpp | 29 +++++++++++-------- .../TelematicBridgePlugin/src/TelematicUnit.h | 6 ++++ .../test/test_TelematicUnit.cpp | 9 ++++++ 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp index e9ed23a33..355fe8fe3 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp @@ -29,18 +29,9 @@ namespace TelematicBridge auto s = natsConnection_RequestString(&reply, _conn, REGISTER_UNIT_TOPIC, payload.c_str(), TIME_OUT); if (s == NATS_OK) { - auto responseStr = natsMsg_GetData(reply); - PLOG(logINFO) << "Received registered reply: " << responseStr; - auto root = parseJson(responseStr); - if (root.isMember(LOCATION) && root.isMember(TESTING_TYPE) && root.isMember(EVENT_NAME)) - { - _eventLocation = root[LOCATION].asString(); - _testingType = root[TESTING_TYPE].asString(); - _eventName = root[EVENT_NAME].asString(); - - // Unit is registered when server responds with event information (location, testing_type, event_name) - _isRegistered = true; - } + auto replyStr = natsMsg_GetData(reply); + PLOG(logINFO) << "Received registered reply: " << replyStr; + updateRegisterStatus(replyStr); natsMsg_Destroy(reply); } else @@ -59,6 +50,20 @@ namespace TelematicBridge } } + void TelematicUnit::updateRegisterStatus(const string ®isterReply) + { + auto root = parseJson(registerReply); + if (root.isMember(LOCATION) && root.isMember(TESTING_TYPE) && root.isMember(EVENT_NAME)) + { + _eventLocation = root[LOCATION].asString(); + _testingType = root[TESTING_TYPE].asString(); + _eventName = root[EVENT_NAME].asString(); + + // Unit is registered when server responds with event information (location, testing_type, event_name) + _isRegistered = true; + } + } + void TelematicUnit::availableTopicsReplier() { if (!_subAvailableTopic) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h index da1e8e455..031439f44 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h @@ -120,6 +120,12 @@ namespace TelematicBridge */ void updateAvailableTopics(const string &newTopic); + /** + * @brief Update telematic unit registration status with the registration reply from NATS server + * @param string Register reply in Json format + */ + void updateRegisterStatus(const string& registerReply); + /** * @brief construct Json data string that will be streamed into the cloud by a publisher * @param unit_st struct that contains unit related information diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp index d93cf96f8..58bc92c2f 100644 --- a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp @@ -133,4 +133,13 @@ namespace TelematicBridge _telematicUnitPtr->clearSelectedTopics(); ASSERT_FALSE(_telematicUnitPtr->inSelectedTopics(selectedTopic)); } + TEST_F(test_TelematicUnit, updateRegisterStatus) + { + string replyStr = "{\"event_name\":\"Test\",\"location\":\"Local\",\"testing_type\":\"Integration\"}"; + _telematicUnitPtr->updateRegisterStatus(replyStr); + ASSERT_EQ("Local", _telematicUnitPtr->getEventLocation()); + ASSERT_EQ("Test", _telematicUnitPtr->getEventName()); + ASSERT_EQ("Integration", _telematicUnitPtr->getTestingType()); + } + } \ No newline at end of file From 8b014689e3a9408c84c9f7f4ed318faeae14e1fe Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 22 Nov 2023 17:57:10 +0000 Subject: [PATCH 30/48] code coverage --- .../TelematicBridgePlugin/src/TelematicUnit.cpp | 17 +++++++++-------- .../TelematicBridgePlugin/src/TelematicUnit.h | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp index 355fe8fe3..fc73a24b0 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp @@ -19,9 +19,9 @@ namespace TelematicBridge void TelematicUnit::registerUnitRequestor() { // Reset registration status - _isRegistered = false; + bool isRegistered = false; - while (!_isRegistered) + while (!isRegistered) { PLOG(logDEBUG2) << "Inside register unit requestor"; natsMsg *reply = nullptr; @@ -31,7 +31,9 @@ namespace TelematicBridge { auto replyStr = natsMsg_GetData(reply); PLOG(logINFO) << "Received registered reply: " << replyStr; - updateRegisterStatus(replyStr); + + // Unit is registered when server responds with event information (location, testing_type, event_name) + isRegistered = updateRegisterStatus(replyStr); natsMsg_Destroy(reply); } else @@ -41,7 +43,7 @@ namespace TelematicBridge sleep(1); } - if (_isRegistered) + if (isRegistered) { // Provide below services when the unit is registered availableTopicsReplier(); @@ -50,7 +52,7 @@ namespace TelematicBridge } } - void TelematicUnit::updateRegisterStatus(const string ®isterReply) + bool TelematicUnit::updateRegisterStatus(const string ®isterReply) { auto root = parseJson(registerReply); if (root.isMember(LOCATION) && root.isMember(TESTING_TYPE) && root.isMember(EVENT_NAME)) @@ -58,10 +60,9 @@ namespace TelematicBridge _eventLocation = root[LOCATION].asString(); _testingType = root[TESTING_TYPE].asString(); _eventName = root[EVENT_NAME].asString(); - - // Unit is registered when server responds with event information (location, testing_type, event_name) - _isRegistered = true; + return true; } + return false; } void TelematicUnit::availableTopicsReplier() diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h index 031439f44..fc15939bd 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h @@ -29,7 +29,6 @@ namespace TelematicBridge mutex _unitMutex; mutex _availableTopicsMutex; mutex _excludedTopicsMutex; - atomic _isRegistered{false}; // Global variable to indicate whether the unit is registered with the NATS server unit_st _unit; // Global variable to store the unit information vector _availableTopics; // Global variable to store available topics string _excludedTopics; // Global variable to store topics that are excluded by the users @@ -123,8 +122,9 @@ namespace TelematicBridge /** * @brief Update telematic unit registration status with the registration reply from NATS server * @param string Register reply in Json format + * @return True when status are updated, otherwise false. */ - void updateRegisterStatus(const string& registerReply); + bool updateRegisterStatus(const string& registerReply); /** * @brief construct Json data string that will be streamed into the cloud by a publisher From 466db6b48d3b08c59eb9ff2b52819a81f1628d11 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 22 Nov 2023 17:59:25 +0000 Subject: [PATCH 31/48] code coverage --- src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp | 6 +++--- src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h | 4 ++-- .../TelematicBridgePlugin/test/test_TelematicUnit.cpp | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp index fc73a24b0..4dfbaf0f4 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp @@ -31,9 +31,9 @@ namespace TelematicBridge { auto replyStr = natsMsg_GetData(reply); PLOG(logINFO) << "Received registered reply: " << replyStr; - + // Unit is registered when server responds with event information (location, testing_type, event_name) - isRegistered = updateRegisterStatus(replyStr); + isRegistered = validateRegisterStatus(replyStr); natsMsg_Destroy(reply); } else @@ -52,7 +52,7 @@ namespace TelematicBridge } } - bool TelematicUnit::updateRegisterStatus(const string ®isterReply) + bool TelematicUnit::validateRegisterStatus(const string ®isterReply) { auto root = parseJson(registerReply); if (root.isMember(LOCATION) && root.isMember(TESTING_TYPE) && root.isMember(EVENT_NAME)) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h index fc15939bd..5b954eb9c 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h @@ -122,9 +122,9 @@ namespace TelematicBridge /** * @brief Update telematic unit registration status with the registration reply from NATS server * @param string Register reply in Json format - * @return True when status are updated, otherwise false. + * @return True when status are validated, otherwise false. */ - bool updateRegisterStatus(const string& registerReply); + bool validateRegisterStatus(const string& registerReply); /** * @brief construct Json data string that will be streamed into the cloud by a publisher diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp index 58bc92c2f..21354ce1e 100644 --- a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp @@ -133,10 +133,10 @@ namespace TelematicBridge _telematicUnitPtr->clearSelectedTopics(); ASSERT_FALSE(_telematicUnitPtr->inSelectedTopics(selectedTopic)); } - TEST_F(test_TelematicUnit, updateRegisterStatus) + TEST_F(test_TelematicUnit, validateRegisterStatus) { string replyStr = "{\"event_name\":\"Test\",\"location\":\"Local\",\"testing_type\":\"Integration\"}"; - _telematicUnitPtr->updateRegisterStatus(replyStr); + _telematicUnitPtr->validateRegisterStatus(replyStr); ASSERT_EQ("Local", _telematicUnitPtr->getEventLocation()); ASSERT_EQ("Test", _telematicUnitPtr->getEventName()); ASSERT_EQ("Integration", _telematicUnitPtr->getTestingType()); From 9ce48c0c7fcc752b5b3455a1341557b505681770 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 27 Nov 2023 14:46:50 +0000 Subject: [PATCH 32/48] add more log --- src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp index 4dfbaf0f4..5f9e662c3 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp @@ -62,6 +62,7 @@ namespace TelematicBridge _eventName = root[EVENT_NAME].asString(); return true; } + PLOG(logERROR) << "Failed to register unit as event information (locatoin, testing type and event name) does not exist."; return false; } From 3e581167b886b7e80a4d284040da565f1259a56b Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 27 Nov 2023 15:30:28 +0000 Subject: [PATCH 33/48] convert timestamp from mill to micro --- src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp | 2 +- src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp index 5f9e662c3..aae696e5b 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp @@ -184,7 +184,7 @@ namespace TelematicBridge message[TESTING_TYPE] = testingType; message[EVENT_NAME] = eventName; message[TOPIC_NAME] = topicName; - message[TIMESTAMP] = payload.isMember("timestamp") ? payload["timestamp"].asUInt64() : duration_cast(system_clock::now().time_since_epoch()).count(); + message[TIMESTAMP] = payload.isMember("timestamp") ? payload["timestamp"].asUInt64() * MILLI_TO_MICRO : duration_cast(system_clock::now().time_since_epoch()).count(); message[PAYLOAD] = payload; Json::FastWriter fasterWirter; string jsonStr = fasterWirter.write(message); diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h index 5b954eb9c..1d93ddc49 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h @@ -56,6 +56,7 @@ namespace TelematicBridge static CONSTEXPR const char *PAYLOAD = "payload"; // payload key used to find payload value from JSON static CONSTEXPR const char *TOPICS = "topics"; // topics key used to find topics value from JSON static CONSTEXPR const char *NAME = "name"; // topics key used to find topics value from JSON + static const uint16_t MILLI_TO_MICRO = 1000; public: /** From 9b4e478f65b5801e943cb98764b0114b5e30e771 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 27 Nov 2023 15:38:00 +0000 Subject: [PATCH 34/48] update unit test --- src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h | 2 +- src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h index 1d93ddc49..1a676b964 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h @@ -56,7 +56,7 @@ namespace TelematicBridge static CONSTEXPR const char *PAYLOAD = "payload"; // payload key used to find payload value from JSON static CONSTEXPR const char *TOPICS = "topics"; // topics key used to find topics value from JSON static CONSTEXPR const char *NAME = "name"; // topics key used to find topics value from JSON - static const uint16_t MILLI_TO_MICRO = 1000; + static const int MILLI_TO_MICRO = 1000; public: /** diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp index 21354ce1e..96947b27d 100644 --- a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp @@ -49,12 +49,13 @@ namespace TelematicBridge string eventName = "testing"; string topicName = "test_topic"; Json::Value payload; - payload["body"] = "test_body"; + payload["timestamp"] = 1701099016033; auto reply = _telematicUnitPtr->constructPublishedDataString(unit, eventLocation, testingType, eventName, topicName, payload); auto json = TelematicUnit::parseJson(reply); ASSERT_EQ(eventLocation, json["location"].asString()); ASSERT_EQ(testingType, json["testing_type"].asString()); ASSERT_EQ(eventName, json["event_name"].asString()); + ASSERT_EQ(1701099016033000, json["timestamp"].asUInt64()); ASSERT_THROW(TelematicUnit::parseJson("Invalid Json"), TelematicBridgeException); } From fbe124c861db3777ff998fa83bdbe07f143ce5c9 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 27 Nov 2023 15:42:20 +0000 Subject: [PATCH 35/48] update unit test --- .../TelematicBridgePlugin/test/test_TelematicUnit.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp index 96947b27d..e52693283 100644 --- a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp @@ -50,6 +50,7 @@ namespace TelematicBridge string topicName = "test_topic"; Json::Value payload; payload["timestamp"] = 1701099016033; + auto reply = _telematicUnitPtr->constructPublishedDataString(unit, eventLocation, testingType, eventName, topicName, payload); auto json = TelematicUnit::parseJson(reply); ASSERT_EQ(eventLocation, json["location"].asString()); @@ -57,6 +58,12 @@ namespace TelematicBridge ASSERT_EQ(eventName, json["event_name"].asString()); ASSERT_EQ(1701099016033000, json["timestamp"].asUInt64()); ASSERT_THROW(TelematicUnit::parseJson("Invalid Json"), TelematicBridgeException); + + Json::Value payload2; + payload2["body"] = "invalid"; + reply = _telematicUnitPtr->constructPublishedDataString(unit, eventLocation, testingType, eventName, topicName, payload2); + json = TelematicUnit::parseJson(reply); + ASSERT_NEAR(duration_cast(system_clock::now().time_since_epoch()).count(), json["timestamp"].asUInt64(), 100); } TEST_F(test_TelematicUnit, onCheckStatusCallback) @@ -136,11 +143,11 @@ namespace TelematicBridge } TEST_F(test_TelematicUnit, validateRegisterStatus) { - string replyStr = "{\"event_name\":\"Test\",\"location\":\"Local\",\"testing_type\":\"Integration\"}"; + string replyStr = "{\"event_name\":\"Test\",\"location\":\"Local\",\"testing_type\":\"Integration\"}"; _telematicUnitPtr->validateRegisterStatus(replyStr); ASSERT_EQ("Local", _telematicUnitPtr->getEventLocation()); ASSERT_EQ("Test", _telematicUnitPtr->getEventName()); ASSERT_EQ("Integration", _telematicUnitPtr->getTestingType()); } - + } \ No newline at end of file From e8678760c97cbb7d5bd212ac07f490793d7d8c63 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 28 Nov 2023 19:30:15 +0000 Subject: [PATCH 36/48] address comments --- .../TelematicBridgePlugin/{readme.md => REAADME.md} | 0 src/v2i-hub/TelematicBridgePlugin/manifest.json | 10 +++++----- 2 files changed, 5 insertions(+), 5 deletions(-) rename src/v2i-hub/TelematicBridgePlugin/{readme.md => REAADME.md} (100%) diff --git a/src/v2i-hub/TelematicBridgePlugin/readme.md b/src/v2i-hub/TelematicBridgePlugin/REAADME.md similarity index 100% rename from src/v2i-hub/TelematicBridgePlugin/readme.md rename to src/v2i-hub/TelematicBridgePlugin/REAADME.md diff --git a/src/v2i-hub/TelematicBridgePlugin/manifest.json b/src/v2i-hub/TelematicBridgePlugin/manifest.json index e150205c7..5d093c64c 100644 --- a/src/v2i-hub/TelematicBridgePlugin/manifest.json +++ b/src/v2i-hub/TelematicBridgePlugin/manifest.json @@ -15,27 +15,27 @@ { "key": "NATSUrl", "default": "nats://127.0.0.1:4222", - "description": "The log level for this plugin" + "description": "The NATS connection URL" }, { "key": "UnitId", "default": "v2xhub_id", - "description": "The log level for this plugin" + "description": "The unique identifier for a telematic unit" }, { "key": "UnitName", "default": "East Intersection", - "description": "The log level for this plugin" + "description": "A descriptive name for each telematic unit" }, { "key": "UnitType", "default": "Infrastructure", - "description": "The log level for this plugin" + "description": "The type of telematic unit. V2xhub belongs to infrastructure category." }, { "key": "TopicExclusionList", "default": "System_KeepAlive_CommandPlugin,System_KeepAlive_CARMAStreetsPlugin,System_KeepAlive_CDASimAdapter,System_KeepAlive_MessageReceiver", - "description": "The list of topics are excluded from the available topic list." + "description": "The list of topics are excluded from the available topic list. Topic name is a combination of message type, subtype and source separated by underscore. E.G: type_subtype_source" } ] } \ No newline at end of file From 986b9797d51818d8f9f730952a431c316b18ccf6 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 29 Nov 2023 14:13:53 +0000 Subject: [PATCH 37/48] address comments --- .../src/TelematicUnit.cpp | 44 +++++++++---------- .../TelematicBridgePlugin/src/TelematicUnit.h | 26 +++++------ 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp index aae696e5b..1f15d8b7c 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp @@ -55,11 +55,11 @@ namespace TelematicBridge bool TelematicUnit::validateRegisterStatus(const string ®isterReply) { auto root = parseJson(registerReply); - if (root.isMember(LOCATION) && root.isMember(TESTING_TYPE) && root.isMember(EVENT_NAME)) + if (root.isMember(LOCATION_KEY) && root.isMember(TESTING_TYPE_KEY) && root.isMember(EVENT_NAME_KEY)) { - _eventLocation = root[LOCATION].asString(); - _testingType = root[TESTING_TYPE].asString(); - _eventName = root[EVENT_NAME].asString(); + _eventLocation = root[LOCATION_KEY].asString(); + _testingType = root[TESTING_TYPE_KEY].asString(); + _eventName = root[EVENT_NAME_KEY].asString(); return true; } PLOG(logERROR) << "Failed to register unit as event information (locatoin, testing type and event name) does not exist."; @@ -177,15 +177,15 @@ namespace TelematicBridge string TelematicUnit::constructPublishedDataString(const unit_st &unit, const string &eventLocation, const string &testingType, const string &eventName, const string &topicName, const Json::Value &payload) const { Json::Value message; - message[UNIT_ID] = unit.unitId; - message[UNIT_NAME] = unit.unitName; - message[UNIT_TYPE] = unit.unitType; - message[LOCATION] = eventLocation; - message[TESTING_TYPE] = testingType; - message[EVENT_NAME] = eventName; - message[TOPIC_NAME] = topicName; - message[TIMESTAMP] = payload.isMember("timestamp") ? payload["timestamp"].asUInt64() * MILLI_TO_MICRO : duration_cast(system_clock::now().time_since_epoch()).count(); - message[PAYLOAD] = payload; + message[UNIT_ID_KEY] = unit.unitId; + message[UNIT_NAME_KEY] = unit.unitName; + message[UNIT_TYPE_KEY] = unit.unitType; + message[LOCATION_KEY] = eventLocation; + message[TESTING_TYPE_KEY] = testingType; + message[EVENT_NAME_KEY] = eventName; + message[TOPIC_NAME_KEY] = topicName; + message[TIMESTAMP_KEY] = payload.isMember("timestamp") ? payload["timestamp"].asUInt64() * MILLI_TO_MICRO : duration_cast(system_clock::now().time_since_epoch()).count(); + message[PAYLOAD_KEY] = payload; Json::FastWriter fasterWirter; string jsonStr = fasterWirter.write(message); return jsonStr; @@ -206,24 +206,24 @@ namespace TelematicBridge string TelematicUnit::constructAvailableTopicsReplyString(const unit_st &unit, const string &eventLocation, const string &testingType, const string &eventName, const vector &availableTopicList, const string &excludedTopics) { Json::Value message; - message[UNIT_ID] = unit.unitId; - message[UNIT_NAME] = unit.unitName; - message[UNIT_TYPE] = unit.unitType; - message[LOCATION] = eventLocation; - message[TESTING_TYPE] = testingType; - message[EVENT_NAME] = eventName; - message[TIMESTAMP] = duration_cast(system_clock::now().time_since_epoch()).count(); + message[UNIT_ID_KEY] = unit.unitId; + message[UNIT_NAME_KEY] = unit.unitName; + message[UNIT_TYPE_KEY] = unit.unitType; + message[LOCATION_KEY] = eventLocation; + message[TESTING_TYPE_KEY] = testingType; + message[EVENT_NAME_KEY] = eventName; + message[TIMESTAMP_KEY] = duration_cast(system_clock::now().time_since_epoch()).count(); Json::Value topics; for (const auto &topic : availableTopicList) { if (!boost::icontains(excludedTopics, topic)) { Json::Value topicJson; - topicJson[NAME] = topic; + topicJson[NAME_KEY] = topic; topics.append(topicJson); } } - message[TOPICS] = topics; + message[TOPICS_KEY] = topics; Json::FastWriter fasterWirter; string reply = fasterWirter.write(message); return reply; diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h index 1a676b964..2c1c3973c 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h @@ -45,17 +45,17 @@ namespace TelematicBridge string _eventName; // Testing event the unit is assigned to string _eventLocation; // Testing event location string _testingType; // Testing type - static CONSTEXPR const char *LOCATION = "location"; // location key used to find location value from JSON - static CONSTEXPR const char *TESTING_TYPE = "testing_type"; // testing_type key used to find testing_type value from JSON - static CONSTEXPR const char *EVENT_NAME = "event_name"; // event_name key used to find event_name value from JSON - static CONSTEXPR const char *UNIT_ID = "unit_id"; // unit_id key used to find unit_id value from JSON - static CONSTEXPR const char *UNIT_NAME = "unit_name"; // unit_name key used to find unit_name value from JSON - static CONSTEXPR const char *UNIT_TYPE = "unit_type"; // unit_type key used to find unit_type value from JSON - static CONSTEXPR const char *TOPIC_NAME = "topic_name"; // topic_name key used to find topic_name value from JSON - static CONSTEXPR const char *TIMESTAMP = "timestamp"; // timestamp key used to find timestamp value from JSON - static CONSTEXPR const char *PAYLOAD = "payload"; // payload key used to find payload value from JSON - static CONSTEXPR const char *TOPICS = "topics"; // topics key used to find topics value from JSON - static CONSTEXPR const char *NAME = "name"; // topics key used to find topics value from JSON + static CONSTEXPR const char *LOCATION_KEY = "location"; // location key used to find location value from JSON + static CONSTEXPR const char *TESTING_TYPE_KEY = "testing_type"; // testing_type key used to find testing_type value from JSON + static CONSTEXPR const char *EVENT_NAME_KEY = "event_name"; // event_name key used to find event_name value from JSON + static CONSTEXPR const char *UNIT_ID_KEY = "unit_id"; // unit_id key used to find unit_id value from JSON + static CONSTEXPR const char *UNIT_NAME_KEY = "unit_name"; // unit_name key used to find unit_name value from JSON + static CONSTEXPR const char *UNIT_TYPE_KEY = "unit_type"; // unit_type key used to find unit_type value from JSON + static CONSTEXPR const char *TOPIC_NAME_KEY = "topic_name"; // topic_name key used to find topic_name value from JSON + static CONSTEXPR const char *TIMESTAMP_KEY = "timestamp"; // timestamp key used to find timestamp value from JSON + static CONSTEXPR const char *PAYLOAD_KEY = "payload"; // payload key used to find payload value from JSON + static CONSTEXPR const char *TOPICS_KEY = "topics"; // topics key used to find topics value from JSON + static CONSTEXPR const char *NAME_KEY = "name"; // topics key used to find topics value from JSON static const int MILLI_TO_MICRO = 1000; public: @@ -121,9 +121,9 @@ namespace TelematicBridge void updateAvailableTopics(const string &newTopic); /** - * @brief Update telematic unit registration status with the registration reply from NATS server + * @brief Update telematic unit registration status when receiving registration reply from NATS server * @param string Register reply in Json format - * @return True when status are validated, otherwise false. + * @return True when reply with event information (location, testing type, event name), otherwise false. */ bool validateRegisterStatus(const string& registerReply); From 4278be866c169dc26fab51f443bce0e04358e3b6 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 29 Nov 2023 14:15:30 +0000 Subject: [PATCH 38/48] address comments --- src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp index 1f15d8b7c..a9e8b704f 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp @@ -139,14 +139,14 @@ namespace TelematicBridge { auto msgStr = natsMsg_GetData(msg); auto root = parseJson(msgStr); - if (object && root.isMember(TOPICS) && root[TOPICS].isArray()) + if (object && root.isMember(TOPICS_KEY) && root[TOPICS_KEY].isArray()) { auto obj = (TelematicUnit *)object; // clear old selected topics obj->clearSelectedTopics(); // update selected topics with selected topics from latest request - for (auto itr = root[TOPICS].begin(); itr != root[TOPICS].end(); itr++) + for (auto itr = root[TOPICS_KEY].begin(); itr != root[TOPICS_KEY].end(); itr++) { obj->addSelectedTopic(itr->asString()); } From 71ac033b94eec7ea112cb5ead2d680a29b769772 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 29 Nov 2023 15:16:26 +0000 Subject: [PATCH 39/48] address comments --- .../{REAADME.md => README.md} | 2 + .../TelematicBridgePlugin/manifest.json | 4 +- .../src/TelematicBridgePlugin.cpp | 7 ++- .../src/TelematicBridgePlugin.h | 19 +++---- .../src/TelematicUnit.cpp | 4 ++ .../TelematicBridgePlugin/src/TelematicUnit.h | 57 +++++++++---------- .../test/test_TelematicUnit.cpp | 3 + 7 files changed, 52 insertions(+), 44 deletions(-) rename src/v2i-hub/TelematicBridgePlugin/{REAADME.md => README.md} (87%) diff --git a/src/v2i-hub/TelematicBridgePlugin/REAADME.md b/src/v2i-hub/TelematicBridgePlugin/README.md similarity index 87% rename from src/v2i-hub/TelematicBridgePlugin/REAADME.md rename to src/v2i-hub/TelematicBridgePlugin/README.md index 87881fbec..6ed0a0497 100644 --- a/src/v2i-hub/TelematicBridgePlugin/REAADME.md +++ b/src/v2i-hub/TelematicBridgePlugin/README.md @@ -1,3 +1,5 @@ +## Telematic bridge introduction +Telematic bridge is a V2xHub plugin used to collect data stream generated by V2xHub and send the data stream into [telematic tool](https://github.com/usdot-fhwa-stol/cda-telematics) hosted in the AWS cloud. ## NATS Publisher/Subscriber ### NATS Connections and registration #### Telematic plugin sends registration request to telematic server diff --git a/src/v2i-hub/TelematicBridgePlugin/manifest.json b/src/v2i-hub/TelematicBridgePlugin/manifest.json index 5d093c64c..0592372fa 100644 --- a/src/v2i-hub/TelematicBridgePlugin/manifest.json +++ b/src/v2i-hub/TelematicBridgePlugin/manifest.json @@ -33,9 +33,9 @@ "description": "The type of telematic unit. V2xhub belongs to infrastructure category." }, { - "key": "TopicExclusionList", + "key": "MessageExclusionList", "default": "System_KeepAlive_CommandPlugin,System_KeepAlive_CARMAStreetsPlugin,System_KeepAlive_CDASimAdapter,System_KeepAlive_MessageReceiver", - "description": "The list of topics are excluded from the available topic list. Topic name is a combination of message type, subtype and source separated by underscore. E.G: type_subtype_source" + "description": "The list of messages are excluded from the available message list. Message name is a combination of message type, subtype and source separated by underscore. E.G: type_subtype_source" } ] } \ No newline at end of file diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index a010c3b2f..0ccc378c7 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -1,5 +1,8 @@ #include "TelematicBridgePlugin.h" +using namespace tmx::utils; +using namespace std; + namespace TelematicBridge { TelematicBridgePlugin::TelematicBridgePlugin(const string &name) : PluginClient(name) @@ -45,12 +48,12 @@ namespace TelematicBridge GetConfigValue("UnitId", _unitId); GetConfigValue("UnitName", _unitName); GetConfigValue("UnitType", _unitType); - GetConfigValue("TopicExclusionList", _excludedTopics); + GetConfigValue("MessageExclusionList", _excludedMessages); unit_st unit = {_unitId, _unitName, _unitType}; if (_telematicUnitPtr) { _telematicUnitPtr->setUnit(unit); - _telematicUnitPtr->updateExcludedTopics(_excludedTopics); + _telematicUnitPtr->updateExcludedTopics(_excludedMessages); } } diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h index 8f03f4dcc..3fca4ae9e 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h @@ -5,25 +5,24 @@ #include "TelematicBridgeMsgWorker.h" #include "TelematicUnit.h" -using namespace tmx::utils; -using namespace std; + namespace TelematicBridge { class TelematicBridgePlugin : public tmx::utils::PluginClient { private: static CONSTEXPR const char *Telematic_MSGTYPE_J2735_STRING = "J2735"; - shared_ptr _telematicUnitPtr; - string _unitId; - string _unitType; - string _unitName; - string _natsURL; - string _excludedTopics; - mutex _configMutex; + std::shared_ptr _telematicUnitPtr; + std::string _unitId; + std::string _unitType; + std::string _unitName; + std::string _natsURL; + std::string _excludedMessages; + std::mutex _configMutex; void OnMessageReceived(IvpMessage *msg); public: - explicit TelematicBridgePlugin(const string &name); + explicit TelematicBridgePlugin(const std::string &name); void OnConfigChanged(const char *key, const char *value) override; void OnStateChange(IvpPluginState state) override; void UpdateConfigSettings(); diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp index a9e8b704f..11c254989 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp @@ -1,5 +1,9 @@ #include "TelematicUnit.h" +using namespace std; +using namespace tmx::utils; +using namespace std::chrono; + namespace TelematicBridge { void TelematicUnit::connect(const string &natsURL) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h index 2c1c3973c..0b9e3694a 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h @@ -10,29 +10,26 @@ #include #include -using namespace std; -using namespace tmx::utils; -using namespace std::chrono; namespace TelematicBridge { using unit_st = struct unit { - string unitId; // Unique identifier for each unit - string unitName; // Descriptive name for each unit - string unitType; // Unit categorized base on unit type: platform or infrastructure + std::string unitId; // Unique identifier for each unit + std::string unitName; // Descriptive name for each unit + std::string unitType; // Unit categorized base on unit type: platform or infrastructure }; class TelematicUnit { private: - mutex _unitMutex; - mutex _availableTopicsMutex; - mutex _excludedTopicsMutex; + std::mutex _unitMutex; + std::mutex _availableTopicsMutex; + std::mutex _excludedTopicsMutex; unit_st _unit; // Global variable to store the unit information - vector _availableTopics; // Global variable to store available topics - string _excludedTopics; // Global variable to store topics that are excluded by the users - vector _selectedTopics; // Global variable to store selected topics confirmed by users + std::vector _availableTopics; // Global variable to store available topics + std::string _excludedTopics; // Global variable to store topics that are excluded by the users + std::vector _selectedTopics; // Global variable to store selected topics confirmed by users static CONSTEXPR const char *AVAILABLE_TOPICS = ".available_topics"; // NATS subject to pub/sub available topics static CONSTEXPR const char *REGISTER_UNIT_TOPIC = "*.register_unit"; // NATS subject to pub/sub registering unit static CONSTEXPR const char *PUBLISH_TOPICS = ".publish_topics"; // NATS subject to publish data stream @@ -42,9 +39,9 @@ namespace TelematicBridge natsSubscription *_subSelectedTopic = nullptr; // Global NATS subscription object natsSubscription *_subCheckStatus = nullptr; // Global NATS subscription object int64_t TIME_OUT = 10000; // NATS Connection time out in milliseconds - string _eventName; // Testing event the unit is assigned to - string _eventLocation; // Testing event location - string _testingType; // Testing type + std::string _eventName; // Testing event the unit is assigned to + std::string _eventLocation; // Testing event location + std::string _testingType; // Testing type static CONSTEXPR const char *LOCATION_KEY = "location"; // location key used to find location value from JSON static CONSTEXPR const char *TESTING_TYPE_KEY = "testing_type"; // testing_type key used to find testing_type value from JSON static CONSTEXPR const char *EVENT_NAME_KEY = "event_name"; // event_name key used to find event_name value from JSON @@ -67,7 +64,7 @@ namespace TelematicBridge * @brief A function for telematic unit to connect to NATS server. Throw exception is connection failed. * * @param string string NATS server URL */ - void connect(const string &natsURL); + void connect(const std::string &natsURL); /** * @brief A NATS requestor for telematic unit to send register request to NATS server. @@ -98,14 +95,14 @@ namespace TelematicBridge /** * @brief A function to publish message stream into NATS server */ - void publishMessage(const string &topic, const Json::Value &payload); + void publishMessage(const std::string &topic, const Json::Value &payload); /** * @brief A function to parse a JSON string and create a JSON object. * @param string input json string * @return Json::Value */ - static Json::Value parseJson(const string &jsonStr); + static Json::Value parseJson(const std::string &jsonStr); /** * @brief construct available topic response @@ -113,19 +110,19 @@ namespace TelematicBridge * @param vector of available topics * @param string Excluded topics separated by commas */ - static string constructAvailableTopicsReplyString(const unit_st &unit, const string &eventLocation, const string &testingType, const string &eventName, const vector &availableTopicList, const string &excludedTopics); + static std::string constructAvailableTopicsReplyString(const unit_st &unit, const std::string &eventLocation, const std::string &testingType, const std::string &eventName, const std::vector &availableTopicList, const std::string &excludedTopics); /** * @brief A function to update available topics global variables when discovering a new topic. */ - void updateAvailableTopics(const string &newTopic); + void updateAvailableTopics(const std::string &newTopic); /** * @brief Update telematic unit registration status when receiving registration reply from NATS server * @param string Register reply in Json format * @return True when reply with event information (location, testing type, event name), otherwise false. */ - bool validateRegisterStatus(const string& registerReply); + bool validateRegisterStatus(const std::string& registerReply); /** * @brief construct Json data string that will be streamed into the cloud by a publisher @@ -136,7 +133,7 @@ namespace TelematicBridge * @param string Topic name is a combination of type_subtype_source from TMX IVPMessage * @param Json::Value Payload is the actual data generated by V2xHub plugin */ - string constructPublishedDataString(const unit_st &unit, const string &eventLocation, const string &testingType, const string &eventName, const string &topicName, const Json::Value &payload) const; + std::string constructPublishedDataString(const unit_st &unit, const std::string &eventLocation, const std::string &testingType, const std::string &eventName, const std::string &topicName, const Json::Value &payload) const; /** * @brief A function to update global unit variable @@ -152,32 +149,32 @@ namespace TelematicBridge /** * @brief Return list of available topics */ - vector getAvailableTopics() const; + std::vector getAvailableTopics() const; /** * @brief Return excluded topics string. */ - string getExcludedTopics() const; + std::string getExcludedTopics() const; /** * @brief Return event name */ - string getEventName() const; + std::string getEventName() const; /** * @brief Return event location */ - string getEventLocation() const; + std::string getEventLocation() const; /** * @brief Return testing type */ - string getTestingType() const; + std::string getTestingType() const; /** * @brief Add new selected topic into the selected topics list */ - void addSelectedTopic(const string &newSelectedTopic); + void addSelectedTopic(const std::string &newSelectedTopic); /** * @brief Clear selected topics list @@ -188,14 +185,14 @@ namespace TelematicBridge * @brief A function to update excluded topics. * @param string Excluded topics separated by commas */ - void updateExcludedTopics(const string &excludedTopics); + void updateExcludedTopics(const std::string &excludedTopics); /** * @brief Check if the given topic is inside the selectedTopics list * @param string A topic to check for existence * @return boolean indicator whether the input topic eixst. */ - bool inSelectedTopics(const string &topic); + bool inSelectedTopics(const std::string &topic); /** * @brief A callback function for available topic replier diff --git a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp index e52693283..9a81427b4 100644 --- a/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/test/test_TelematicUnit.cpp @@ -1,5 +1,8 @@ #include #include "TelematicUnit.h" +using namespace std; +using namespace tmx::utils; +using namespace std::chrono; namespace TelematicBridge { From 1c59a3e2d0a95ea4ab44bc691b001aad589bd19c Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 29 Nov 2023 15:29:26 +0000 Subject: [PATCH 40/48] address comments --- src/v2i-hub/TelematicBridgePlugin/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/manifest.json b/src/v2i-hub/TelematicBridgePlugin/manifest.json index 0592372fa..f3afc600c 100644 --- a/src/v2i-hub/TelematicBridgePlugin/manifest.json +++ b/src/v2i-hub/TelematicBridgePlugin/manifest.json @@ -25,7 +25,7 @@ { "key": "UnitName", "default": "East Intersection", - "description": "A descriptive name for each telematic unit" + "description": "A descriptive name for each telematic unit. It can also be the intersection name where this unit collect data from." }, { "key": "UnitType", From d5998cf26339e7da466a751de298804391f2ad1c Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 29 Nov 2023 16:05:38 +0000 Subject: [PATCH 41/48] address comments --- src/v2i-hub/TelematicBridgePlugin/manifest.json | 5 ----- .../TelematicBridgePlugin/src/TelematicBridgePlugin.cpp | 3 +-- .../TelematicBridgePlugin/src/TelematicBridgePlugin.h | 2 +- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/manifest.json b/src/v2i-hub/TelematicBridgePlugin/manifest.json index f3afc600c..149baef92 100644 --- a/src/v2i-hub/TelematicBridgePlugin/manifest.json +++ b/src/v2i-hub/TelematicBridgePlugin/manifest.json @@ -27,11 +27,6 @@ "default": "East Intersection", "description": "A descriptive name for each telematic unit. It can also be the intersection name where this unit collect data from." }, - { - "key": "UnitType", - "default": "Infrastructure", - "description": "The type of telematic unit. V2xhub belongs to infrastructure category." - }, { "key": "MessageExclusionList", "default": "System_KeepAlive_CommandPlugin,System_KeepAlive_CARMAStreetsPlugin,System_KeepAlive_CDASimAdapter,System_KeepAlive_MessageReceiver", diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index 0ccc378c7..d17412c2d 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -47,9 +47,8 @@ namespace TelematicBridge GetConfigValue("NATSUrl", _natsURL); GetConfigValue("UnitId", _unitId); GetConfigValue("UnitName", _unitName); - GetConfigValue("UnitType", _unitType); GetConfigValue("MessageExclusionList", _excludedMessages); - unit_st unit = {_unitId, _unitName, _unitType}; + unit_st unit = {_unitId, _unitName, UNIT_TYPE_INFRASTRUCTURE}; if (_telematicUnitPtr) { _telematicUnitPtr->setUnit(unit); diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h index 3fca4ae9e..c7640db5a 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h @@ -12,9 +12,9 @@ namespace TelematicBridge { private: static CONSTEXPR const char *Telematic_MSGTYPE_J2735_STRING = "J2735"; + static CONSTEXPR const char *UNIT_TYPE_INFRASTRUCTURE = "Infrastructure"; std::shared_ptr _telematicUnitPtr; std::string _unitId; - std::string _unitType; std::string _unitName; std::string _natsURL; std::string _excludedMessages; From 040a99b1b4e251b04731c572cbc2da450bd0bcd0 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 29 Nov 2023 19:30:46 +0000 Subject: [PATCH 42/48] address comments --- .../TelematicBridgePlugin/src/TelematicBridgePlugin.cpp | 2 +- src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h | 2 +- src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp | 4 +++- src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index d17412c2d..34110f180 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -7,7 +7,7 @@ namespace TelematicBridge { TelematicBridgePlugin::TelematicBridgePlugin(const string &name) : PluginClient(name) { - _telematicUnitPtr = make_shared(); + _telematicUnitPtr = make_unique(); UpdateConfigSettings(); AddMessageFilter("*", "*", IvpMsgFlags_None); AddMessageFilter("J2735", "*", IvpMsgFlags_RouteDSRC); diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h index c7640db5a..f4989db05 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h @@ -13,7 +13,7 @@ namespace TelematicBridge private: static CONSTEXPR const char *Telematic_MSGTYPE_J2735_STRING = "J2735"; static CONSTEXPR const char *UNIT_TYPE_INFRASTRUCTURE = "Infrastructure"; - std::shared_ptr _telematicUnitPtr; + std::unique_ptr _telematicUnitPtr; std::string _unitId; std::string _unitName; std::string _natsURL; diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp index 11c254989..e99029b53 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.cpp @@ -24,9 +24,11 @@ namespace TelematicBridge { // Reset registration status bool isRegistered = false; + int attempts_count = 0; - while (!isRegistered) + while (!isRegistered && attempts_count < REGISTRATION_MAX_ATTEMPTS) { + attempts_count++; PLOG(logDEBUG2) << "Inside register unit requestor"; natsMsg *reply = nullptr; string payload = "{\"unit_id\":\"" + _unit.unitId + "\"}"; diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h index 0b9e3694a..3a72f080b 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicUnit.h @@ -54,6 +54,7 @@ namespace TelematicBridge static CONSTEXPR const char *TOPICS_KEY = "topics"; // topics key used to find topics value from JSON static CONSTEXPR const char *NAME_KEY = "name"; // topics key used to find topics value from JSON static const int MILLI_TO_MICRO = 1000; + static const int REGISTRATION_MAX_ATTEMPTS = 30; //The maximum numbers of attempts allowed to register this unit with server public: /** From bf290f51d257e27148b9fd0aa77e0e9b371a9ed3 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 30 Nov 2023 16:47:29 +0000 Subject: [PATCH 43/48] address comments --- .devcontainer/docker-compose-vscode.yml | 3 ++- configuration/amd64/docker-compose.yml | 2 ++ src/tmx/TmxUtils/src/simulation/SimulationEnvUtils.h | 6 ++++++ .../TelematicBridgePlugin/src/TelematicBridgePlugin.cpp | 5 +++-- .../TelematicBridgePlugin/src/TelematicBridgePlugin.h | 1 + 5 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.devcontainer/docker-compose-vscode.yml b/.devcontainer/docker-compose-vscode.yml index cc113ce62..9035d1f9d 100755 --- a/.devcontainer/docker-compose-vscode.yml +++ b/.devcontainer/docker-compose-vscode.yml @@ -24,7 +24,8 @@ services: - SIM_V2X_PORT=5757 - SIM_INTERACTION_PORT=7576 - V2X_PORT=8686 - - INFRASTRUCTURE_ID=1 + - INFRASTRUCTURE_ID=rsu_ + - INFRASTRUCTURE_NAME= - SENSOR_JSON_FILE_PATH=/var/www/plugins/MAP/sensors.json secrets: - mysql_password diff --git a/configuration/amd64/docker-compose.yml b/configuration/amd64/docker-compose.yml index 6b5188297..0c9d5feb2 100755 --- a/configuration/amd64/docker-compose.yml +++ b/configuration/amd64/docker-compose.yml @@ -38,6 +38,8 @@ services: - db environment: - MYSQL_PASSWORD=/run/secrets/mysql_password + - INFRASTRUCTURE_ID=rsu_ + - INFRASTRUCTURE_NAME= secrets: - mysql_password volumes: diff --git a/src/tmx/TmxUtils/src/simulation/SimulationEnvUtils.h b/src/tmx/TmxUtils/src/simulation/SimulationEnvUtils.h index 7498a7922..efffc4ffa 100644 --- a/src/tmx/TmxUtils/src/simulation/SimulationEnvUtils.h +++ b/src/tmx/TmxUtils/src/simulation/SimulationEnvUtils.h @@ -66,6 +66,12 @@ namespace tmx::utils::sim{ * for CDASim connection. */ constexpr inline static const char *INFRASTRUCTURE_ID = "INFRASTRUCTURE_ID"; + + /** + * @brief Name of environment variable for storing infrastructure name of v2xhub. Only necessary in SIMULATION MODE + * for CDASim connection. + */ + constexpr inline static const char *INFRASTRUCTURE_NAME = "INFRASTRUCTURE_NAME"; /** * @brief Function to return bool indicating whether V2X-Hub deployment is in SIMULATION MODE or not. * @return true if SIMULATION_MODE is "true" or "TRUE" and false otherwise. diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index 34110f180..792ee3b9e 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -8,6 +8,9 @@ namespace TelematicBridge TelematicBridgePlugin::TelematicBridgePlugin(const string &name) : PluginClient(name) { _telematicUnitPtr = make_unique(); + _unitId = sim::get_sim_config("INFRASTRUCTURE_ID"); + _unitName = sim::get_sim_config("INFRASTRUCTURE_NAME"); + PLOG(logERROR) << "_unitId: "<< _unitId; UpdateConfigSettings(); AddMessageFilter("*", "*", IvpMsgFlags_None); AddMessageFilter("J2735", "*", IvpMsgFlags_RouteDSRC); @@ -45,8 +48,6 @@ namespace TelematicBridge { lock_guard lock(_configMutex); GetConfigValue("NATSUrl", _natsURL); - GetConfigValue("UnitId", _unitId); - GetConfigValue("UnitName", _unitName); GetConfigValue("MessageExclusionList", _excludedMessages); unit_st unit = {_unitId, _unitName, UNIT_TYPE_INFRASTRUCTURE}; if (_telematicUnitPtr) diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h index f4989db05..a75b21bbe 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.h @@ -4,6 +4,7 @@ #include "PluginClient.h" #include "TelematicBridgeMsgWorker.h" #include "TelematicUnit.h" +#include namespace TelematicBridge From e1d73150c934bd92fbae26849e458710706d0c60 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 30 Nov 2023 18:01:59 +0000 Subject: [PATCH 44/48] address comments --- configuration/amd64/docker-compose.yml | 1 + src/v2i-hub/TelematicBridgePlugin/manifest.json | 10 ---------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/configuration/amd64/docker-compose.yml b/configuration/amd64/docker-compose.yml index 0c9d5feb2..3341eca03 100755 --- a/configuration/amd64/docker-compose.yml +++ b/configuration/amd64/docker-compose.yml @@ -37,6 +37,7 @@ services: depends_on: - db environment: + - SIMULATION_MODE=true - MYSQL_PASSWORD=/run/secrets/mysql_password - INFRASTRUCTURE_ID=rsu_ - INFRASTRUCTURE_NAME= diff --git a/src/v2i-hub/TelematicBridgePlugin/manifest.json b/src/v2i-hub/TelematicBridgePlugin/manifest.json index 149baef92..d133ceb0f 100644 --- a/src/v2i-hub/TelematicBridgePlugin/manifest.json +++ b/src/v2i-hub/TelematicBridgePlugin/manifest.json @@ -17,16 +17,6 @@ "default": "nats://127.0.0.1:4222", "description": "The NATS connection URL" }, - { - "key": "UnitId", - "default": "v2xhub_id", - "description": "The unique identifier for a telematic unit" - }, - { - "key": "UnitName", - "default": "East Intersection", - "description": "A descriptive name for each telematic unit. It can also be the intersection name where this unit collect data from." - }, { "key": "MessageExclusionList", "default": "System_KeepAlive_CommandPlugin,System_KeepAlive_CARMAStreetsPlugin,System_KeepAlive_CDASimAdapter,System_KeepAlive_MessageReceiver", From ebaa4218c21a181e28e1fd9e97289c7689e67fba Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 30 Nov 2023 18:27:43 +0000 Subject: [PATCH 45/48] address comments --- configuration/amd64/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration/amd64/docker-compose.yml b/configuration/amd64/docker-compose.yml index 3341eca03..40449cfeb 100755 --- a/configuration/amd64/docker-compose.yml +++ b/configuration/amd64/docker-compose.yml @@ -37,8 +37,8 @@ services: depends_on: - db environment: - - SIMULATION_MODE=true - MYSQL_PASSWORD=/run/secrets/mysql_password + - SIMULATION_MODE=true - INFRASTRUCTURE_ID=rsu_ - INFRASTRUCTURE_NAME= secrets: From 1fee07192eb8406a279c77884854de912756bb24 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 30 Nov 2023 18:28:42 +0000 Subject: [PATCH 46/48] address comments --- configuration/amd64/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration/amd64/docker-compose.yml b/configuration/amd64/docker-compose.yml index 40449cfeb..e67fc6084 100755 --- a/configuration/amd64/docker-compose.yml +++ b/configuration/amd64/docker-compose.yml @@ -38,7 +38,7 @@ services: - db environment: - MYSQL_PASSWORD=/run/secrets/mysql_password - - SIMULATION_MODE=true + - SIMULATION_MODE=false - INFRASTRUCTURE_ID=rsu_ - INFRASTRUCTURE_NAME= secrets: From 691178f109fdc0a83f2607c47184fd8b125046a1 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 30 Nov 2023 18:49:10 +0000 Subject: [PATCH 47/48] address comments --- configuration/amd64/docker-compose.yml | 2 +- src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/configuration/amd64/docker-compose.yml b/configuration/amd64/docker-compose.yml index e67fc6084..40449cfeb 100755 --- a/configuration/amd64/docker-compose.yml +++ b/configuration/amd64/docker-compose.yml @@ -38,7 +38,7 @@ services: - db environment: - MYSQL_PASSWORD=/run/secrets/mysql_password - - SIMULATION_MODE=false + - SIMULATION_MODE=true - INFRASTRUCTURE_ID=rsu_ - INFRASTRUCTURE_NAME= secrets: diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index 792ee3b9e..d32b36000 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -10,7 +10,6 @@ namespace TelematicBridge _telematicUnitPtr = make_unique(); _unitId = sim::get_sim_config("INFRASTRUCTURE_ID"); _unitName = sim::get_sim_config("INFRASTRUCTURE_NAME"); - PLOG(logERROR) << "_unitId: "<< _unitId; UpdateConfigSettings(); AddMessageFilter("*", "*", IvpMsgFlags_None); AddMessageFilter("J2735", "*", IvpMsgFlags_RouteDSRC); From 9d89744490ece1c3ec746b383306c86a4dcc4ecd Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 30 Nov 2023 18:50:49 +0000 Subject: [PATCH 48/48] address comments --- configuration/amd64/docker-compose.yml | 1 - .../TelematicBridgePlugin/src/TelematicBridgePlugin.cpp | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/configuration/amd64/docker-compose.yml b/configuration/amd64/docker-compose.yml index 40449cfeb..0c9d5feb2 100755 --- a/configuration/amd64/docker-compose.yml +++ b/configuration/amd64/docker-compose.yml @@ -38,7 +38,6 @@ services: - db environment: - MYSQL_PASSWORD=/run/secrets/mysql_password - - SIMULATION_MODE=true - INFRASTRUCTURE_ID=rsu_ - INFRASTRUCTURE_NAME= secrets: diff --git a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp index d32b36000..44a6738f2 100644 --- a/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp +++ b/src/v2i-hub/TelematicBridgePlugin/src/TelematicBridgePlugin.cpp @@ -8,8 +8,8 @@ namespace TelematicBridge TelematicBridgePlugin::TelematicBridgePlugin(const string &name) : PluginClient(name) { _telematicUnitPtr = make_unique(); - _unitId = sim::get_sim_config("INFRASTRUCTURE_ID"); - _unitName = sim::get_sim_config("INFRASTRUCTURE_NAME"); + _unitId = std::getenv("INFRASTRUCTURE_ID"); + _unitName = std::getenv("INFRASTRUCTURE_NAME"); UpdateConfigSettings(); AddMessageFilter("*", "*", IvpMsgFlags_None); AddMessageFilter("J2735", "*", IvpMsgFlags_RouteDSRC);