-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
modified: src/tmx/TmxApi/tmx/TmxApiMessages.h
modified: src/v2i-hub/ImmediateForwardPlugin/manifest.json new file: src/v2i-hub/RsmPlugin/CMakeLists.txt new file: src/v2i-hub/RsmPlugin/manifest.json new file: src/v2i-hub/RsmPlugin/src/RsmPlugin.cpp new file: src/v2i-hub/RsmPlugin/src/RsmPluginWorker.cpp new file: src/v2i-hub/RsmPlugin/src/include/RsmPlugin.hpp new file: src/v2i-hub/RsmPlugin/src/include/RsmPluginWorker.hpp
- Loading branch information
1 parent
564394e
commit 0dad656
Showing
8 changed files
with
452 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
PROJECT ( RsmPlugin VERSION 7.5.1 LANGUAGES CXX ) | ||
|
||
SET (TMX_PLUGIN_NAME "RSM") | ||
add_compile_options(-fPIC) | ||
FIND_PACKAGE (XercesC REQUIRED) | ||
|
||
find_package(Qt5Core REQUIRED) | ||
find_package(Qt5Widgets REQUIRED) | ||
find_package(Qt5Network REQUIRED) | ||
|
||
find_package(qserverPedestrian REQUIRED) | ||
|
||
include_directories(${Qt5Widgets_INCLUDE_DIRS}) | ||
|
||
include_directories(${EXTERNAL_INSTALL_LOCATION}/include) | ||
link_directories(${EXTERNAL_INSTALL_LOCATION}/lib) | ||
|
||
find_library(libasn1c .) | ||
|
||
include_directories( | ||
${Qt5Core_INCLUDE_DIRS} | ||
${Qt5Network_INCLUDE_DIRS} | ||
) | ||
|
||
|
||
BuildTmxPlugin () | ||
|
||
|
||
|
||
TARGET_INCLUDE_DIRECTORIES ( ${PROJECT_NAME} PUBLIC ${XercesC_INCLUDE_DIRS} ${NETSNMP_INCLUDE_DIRS} ${Qt5Core_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS}) | ||
|
||
TARGET_LINK_LIBRARIES ( ${PROJECT_NAME} PUBLIC tmxutils ${XercesC_LIBRARY} ${NETSNMP_LIBRARIES} ${QHttpEngine_LIBRARY} Qt5Widgets Qt5Core Qt5Network ssl crypto qhttpengine qserverPedestrian) | ||
|
||
|
||
link_directories(${CMAKE_PREFIX_PATH}/lib) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
{ | ||
"name":"RSM", | ||
"description":"Provides Road Safety Message (RSM).", | ||
"version":"@PROJECT_VERSION@", | ||
"exeLocation":"/bin/RsmPlugin", | ||
"coreIpAddr":"127.0.0.1", | ||
"corePort":24601, | ||
"messageTypes":[ | ||
{ | ||
"type":"J2735", | ||
"subtype":"RSM", | ||
"description":"Road Safety Message used to provide road safety information to travelers." | ||
} | ||
], | ||
"configuration":[ | ||
{ | ||
"key":"Interval", | ||
"default":"1000", | ||
"description":"The interval to send the RSM, in milliseconds." | ||
}, | ||
{ | ||
"key":"WebServiceIP", | ||
"default":"127.0.0.1", | ||
"description":"IP address at which the web service exists" | ||
}, | ||
{ | ||
"key":"WebServicePort", | ||
"default":"12000", | ||
"description":"Port at which Web service exists" | ||
}, | ||
{ | ||
"key":"LogLevel", | ||
"default":"DEBUG", | ||
"description": "RSM Plugin Log Level controls which log statements are printed to the terminal." | ||
} | ||
|
||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,232 @@ | ||
//========================================================================== | ||
// Name : RsmPlugin.cpp | ||
// Author : FHWA Saxton Transportation Operations Laboratory | ||
// Version : | ||
// Copyright : Copyright (c) 2023 FHWA Saxton Transportation Operations Laboratory. All rights reserved. | ||
// Description : Rsm Plugin | ||
//========================================================================== | ||
|
||
#include "include/RsmPlugin.hpp" | ||
|
||
namespace RsmPlugin | ||
{ | ||
/** | ||
* Construct a new RsmPlugin with the given name. | ||
* | ||
* @param name The name to give the plugin for identification purposes. | ||
*/ | ||
RsmPlugin::RsmPlugin(string name): PluginClient(name) | ||
{ | ||
// The log level can be changed from the default here. | ||
FILELog::ReportingLevel() = FILELog::FromString("DEBUG"); | ||
|
||
AddMessageFilter<RsmMessage>(this, &RsmPlugin::HandleRoadSafetyMessage); | ||
|
||
// Subscribe to all messages specified by the filters above. | ||
SubscribeToMessages(); | ||
} | ||
|
||
void RsmPlugin::RsmRequestHandler(QHttpEngine::Socket *socket) | ||
{ | ||
if(socket->bytesAvailable() == 0) | ||
{ | ||
PLOG(logERROR) << "RSM Plugin does not receive web service request content!" << endl; | ||
writeResponse(QHttpEngine::Socket::BadRequest, socket); | ||
return; | ||
} | ||
|
||
// should read from the websocket and parse | ||
QString st; | ||
while(socket->bytesAvailable()>0) | ||
{ | ||
st.append(socket->readAll()); | ||
} | ||
QByteArray array = st.toLocal8Bit(); | ||
|
||
char* rsmMsgdef = array.data(); | ||
// Catch parse exceptions | ||
|
||
stringstream ss; | ||
ss << rsmMsgdef; | ||
PLOG(logDEBUG) << "Received from webservice: " << ss.str() << endl; | ||
|
||
try { | ||
BroadcastRsm(rsmMsgdef); | ||
writeResponse(QHttpEngine::Socket::Created, socket); | ||
} | ||
catch (TmxException &ex) { | ||
PLOG(logERROR) << "Failed to encode message : " << ex.what(); | ||
writeResponse(QHttpEngine::Socket::BadRequest, socket); | ||
} | ||
} | ||
|
||
|
||
int RsmPlugin::StartWebService() | ||
{ | ||
//Web services | ||
char *placeholderX[1]={0}; | ||
int placeholderC=1; | ||
QCoreApplication a(placeholderC,placeholderX); | ||
|
||
QHostAddress address = QHostAddress(QString::fromStdString (webip)); | ||
quint16 port = static_cast<quint16>(webport); | ||
|
||
|
||
QSharedPointer<OpenAPI::OAIApiRequestHandler> handler(new OpenAPI::OAIApiRequestHandler()); | ||
handler = QSharedPointer<OpenAPI::OAIApiRequestHandler> (new OpenAPI::OAIApiRequestHandler()); | ||
|
||
auto router = QSharedPointer<OpenAPI::OAIApiRouter>::create(); | ||
router->setUpRoutes(); | ||
|
||
QObject::connect(handler.data(), &OpenAPI::OAIApiRequestHandler::requestReceived, [&](QHttpEngine::Socket *socket) { | ||
|
||
this->RsmRequestHandler(socket); | ||
}); | ||
|
||
QObject::connect(handler.data(), &OpenAPI::OAIApiRequestHandler::requestReceived, [&](QHttpEngine::Socket *socket) { | ||
router->processRequest(socket); | ||
}); | ||
|
||
QHttpEngine::Server server(handler.data()); | ||
|
||
if (!server.listen(address, port)) { | ||
qCritical("RsmPlugin:: Unable to listen on the specified port."); | ||
return 1; | ||
} | ||
PLOG(logINFO)<<"RsmPlugin:: Started web service"; | ||
return a.exec(); | ||
|
||
} | ||
|
||
RsmPlugin::~RsmPlugin() | ||
{ | ||
if (_signSimClient != NULL) | ||
delete _signSimClient; | ||
} | ||
|
||
void RsmPlugin::UpdateConfigSettings() | ||
{ | ||
// Configuration settings are retrieved from the API using the GetConfigValue template class. | ||
// This method does NOT execute in the main thread, so variables must be protected | ||
// (e.g. using atomic, mutex, etc.). | ||
|
||
lock_guard<mutex> lock(_cfgLock); | ||
|
||
GetConfigValue<string>("WebServiceIP", webip); | ||
GetConfigValue<uint16_t>("WebServicePort", webport); | ||
} | ||
|
||
void RsmPlugin::OnConfigChanged(const char *key, const char *value) | ||
{ | ||
PluginClient::OnConfigChanged(key, value); | ||
UpdateConfigSettings(); | ||
} | ||
|
||
void RsmPlugin::OnStateChange(IvpPluginState state) | ||
{ | ||
PluginClient::OnStateChange(state); | ||
|
||
if (state == IvpPluginState_registered) | ||
{ | ||
UpdateConfigSettings(); | ||
// Start webservice needs to occur after the first updateConfigSettings call to acquire port and ip configurations. | ||
// Also needs to be called from Main thread to work. | ||
thread webthread(&RsmPlugin::StartWebService, this); | ||
webthread.detach(); // wait for the thread to finish | ||
} | ||
} | ||
|
||
void RsmPlugin::HandleRoadSafetyMessage(RsmMessage &msg, routeable_message &routeableMsg) | ||
{ | ||
PLOG(logDEBUG)<<"HandleRoadSafetyMessage"; | ||
} | ||
|
||
void RsmPlugin::BroadcastRsm(char * rsmJson) | ||
{ | ||
|
||
RsmMessage rsmmessage; | ||
RsmEncodedMessage rsmENC; | ||
tmx::message_container_type container; | ||
unique_ptr<RsmEncodedMessage> msg; | ||
|
||
try | ||
{ | ||
stringstream ss; | ||
ss << rsmJson; | ||
|
||
container.load<XML>(ss); | ||
rsmmessage.set_contents(container.get_storage().get_tree()); | ||
|
||
const string rsmString(rsmJson); | ||
|
||
rsmENC.encode_j2735_message(rsmmessage); | ||
|
||
msg.reset(); | ||
msg.reset(dynamic_cast<RsmEncodedMessage*>(factory.NewMessage(api::MSGSUBTYPE_ROADSAFETYMESSAGE_STRING))); | ||
|
||
string enc = rsmENC.get_encoding(); | ||
msg->refresh_timestamp(); | ||
msg->set_payload(rsmENC.get_payload_str()); | ||
msg->set_encoding(enc); | ||
msg->set_flags(IvpMsgFlags_RouteDSRC); | ||
msg->addDsrcMetadata(0x8003); | ||
msg->refresh_timestamp(); | ||
|
||
routeable_message *rMsg = dynamic_cast<routeable_message *>(msg.get()); | ||
BroadcastMessage(*rMsg); | ||
|
||
PLOG(logINFO) << " RSM Plugin :: Broadcast RSM:: " << rsmENC.get_payload_str(); | ||
} | ||
catch(const exception& e) | ||
{ | ||
PLOG(logWARNING) << "Error: " << e.what() << " broadcasting RSM for xml: " << rsmJson << endl; | ||
} | ||
|
||
|
||
|
||
} | ||
|
||
/** | ||
* Write HTTP response. | ||
*/ | ||
void RsmPlugin::writeResponse(int responseCode , QHttpEngine::Socket *socket) { | ||
socket->setStatusCode(responseCode); | ||
socket->writeHeaders(); | ||
if(socket->isOpen()){ | ||
socket->close(); | ||
} | ||
|
||
} | ||
|
||
|
||
int RsmPlugin::Main() | ||
{ | ||
PLOG(logINFO) << "RsmPlugin:: Starting plugin.\n"; | ||
|
||
uint msCount = 0; | ||
while (_plugin->state != IvpPluginState_error) | ||
{ | ||
|
||
msCount += 10; | ||
|
||
if (_plugin->state == IvpPluginState_registered) | ||
{ | ||
RoadSafetyMessage rsm_1; | ||
RoadSafetyMessage &rsm = rsm_1; | ||
|
||
this_thread::sleep_for(chrono::milliseconds(100)); | ||
|
||
msCount = 0; | ||
} | ||
} | ||
|
||
PLOG(logINFO) << "Plugin terminating gracefully."; | ||
return EXIT_SUCCESS; | ||
} | ||
|
||
} /* namespace RsmPlugin */ | ||
|
||
int main(int argc, char *argv[]) | ||
{ | ||
return run_plugin<RsmPlugin::RsmPlugin>("RsmPlugin", argc, argv); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
//========================================================================== | ||
// Name : RsmPlugin.cpp | ||
// Author : FHWA Saxton Transportation Operations Laboratory | ||
// Version : | ||
// Copyright : Copyright (c) 2024 FHWA Saxton Transportation Operations Laboratory. All rights reserved. | ||
// Description : RSM Plugin | ||
//========================================================================== | ||
|
||
#include "include/RsmPluginWorker.hpp" | ||
|
||
using namespace std; | ||
|
||
namespace RsmPlugin { | ||
|
||
}; |
Oops, something went wrong.