-
Notifications
You must be signed in to change notification settings - Fork 67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
v2x hub Integration: Implement telematic plugin to subscribe to all TMX messages from V2xHub #565
Changes from 12 commits
2cb49ca
9b685ae
d9dddf9
614941b
4b4a8b8
f21faab
0fac3f8
47de4e6
30d8528
eece9af
b9d209e
8b4d24d
5ca81e0
a3b68aa
2f951d4
9e63a6a
31f0be3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,9 @@ DEPENDENCIES="build-essential \ | |
wget \ | ||
zip \ | ||
zlib1g \ | ||
rapidjson-dev \ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason we need to use rapidjson instead of any of the json libraries we currently have installed in V2X-Hub There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the xml to json library use the rapidjson lib |
||
librapidxml-dev \ | ||
libprotobuf-c-dev \ | ||
curl" | ||
|
||
# STOL library dependencies | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -145,7 +145,11 @@ namespace RSUHealthMonitor | |
} | ||
else if (success) | ||
{ | ||
rsuStatuJson.append(populateJson(config.field, responseVal)); | ||
auto json = populateJson(config.field, responseVal); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What changed here for the RSU Health Monitor Plugin There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The JSON was an array. My intention is to create a JSON object. |
||
for(const auto &key: json.getMemberNames()) | ||
{ | ||
rsuStatuJson[key] = json[key]; | ||
} | ||
} | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why this change? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This unit test sometimes failed. https://github.com/usdot-fhwa-OPS/V2X-Hub/actions/runs/6895436333/job/18759375988 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I ran the unit test in local and the list count sometimes equals to 1, sometimes equals to 2. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a issue. Can we create a bug for this is we do not plan to address it in this PR and leave a TODO comment here outlining what you found. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
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); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 jsoncpp) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if we are not linking rapidjson, what is the point of finding the package? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
#################################################### | ||
################## Testing ####################### | ||
#################################################### | ||
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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you link the following you do not need to create a target_link_libraries(${PROJECT_NAME}_test PRIVATE ${PROJECT_NAME}_lib GTest::Main There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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": [], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update Message Types here if we want status counts for the messages this plugin handles. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This plugin intents to subscribe to all messages. what exact messageTypes should be list here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The same as Immediate Forward plugin, messageTypes is empty array. |
||
"configuration": [ | ||
{ | ||
"key": "LogLevel", | ||
"default": "INFO", | ||
"description": "The log level for this plugin" | ||
} | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#pragma once | ||
#include <tmx/TmxException.hpp> | ||
|
||
namespace TelematicBridge | ||
{ | ||
class TelematicBridgeException : public tmx::TmxException | ||
{ | ||
public: | ||
using TmxException::TmxException; | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
#include "TelematicBridgeMsgWorker.h" | ||
|
||
namespace TelematicBridge | ||
{ | ||
bool TelematicBridgeMsgWorker::HexToBytes(const string &hexPaylod, vector<char> &byteBuffer) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is this method for? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added comments |
||
{ | ||
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<char> 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(""); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is this erroross object? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ostringstream |
||
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<void *>(&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<buffer_structure_t *>(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<char *>(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<double>(msg->payload->valueint)); | ||
} | ||
else | ||
{ | ||
json["payload"] = StringToJson(cJSON_Print(msg->payload)); | ||
} | ||
} | ||
|
||
return json; | ||
} | ||
} // TelematicBridge |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After we install this dependency, we should delete the source code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed a3b68aa