Skip to content

Commit

Permalink
modified: src/tmx/TmxApi/tmx/TmxApiMessages.h
Browse files Browse the repository at this point in the history
	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
jwillmartin committed Mar 25, 2024
1 parent 564394e commit 0dad656
Show file tree
Hide file tree
Showing 8 changed files with 452 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/tmx/TmxApi/tmx/TmxApiMessages.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ static CONSTEXPR const char *MSGPSID_SIGNALCONTROLANDPRIORITIZATIONREQUEST_PSID_
static CONSTEXPR const char *MSGPSID_SIGNALCONTROLANDPRIORITIZATIONSTATUS_PSID_STRING = "0xE0000015";
static CONSTEXPR const char *MSGPSID_ROADUSERCHARGINGCONFIGMESSAGE_PSID_STRING = "0x800F";
static CONSTEXPR const char *MSGPSID_ROADUSERCHARGINGREPORTMESSAGE_PSID_STRING = "0x800F";
static CONSTEXPR const char *MSGPSID_TRAFFICLIGHTSTATUSMESSAGE_PSID_STRING = "TLSM";
static CONSTEXPR const char *MSGPSID_TRAFFICLIGHTSTATUSMESSAGE_PSID_STRING = "0x8002";
static CONSTEXPR const char *MSGPSID_TESTMESSAGE00_PSID_STRING = "0xBFEE";
static CONSTEXPR const char *MSGPSID_TESTMESSAGE01_PSID_STRING = "0xBFEE";
static CONSTEXPR const char *MSGPSID_TESTMESSAGE02_PSID_STRING = "0xBFEE";
Expand Down
2 changes: 1 addition & 1 deletion src/v2i-hub/ImmediateForwardPlugin/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
},
{
"key": "Messages_Destination_1",
"default": "{ \"Messages\": [ { \"TmxType\": \"SPAT-P\", \"SendType\": \"SPAT\", \"PSID\": \"0x8002\", \"Channel\": \"183\" }, { \"TmxType\": \"MAP-P\", \"SendType\": \"MAP\", \"PSID\": \"0x8002\", \"Channel\": \"183\" }, { \"TmxType\": \"PSM-P\", \"SendType\": \"PSM\", \"PSID\": \"0x27\", \"Channel\": \"183\" } ,{ \"TmxType\": \"TMSG07-P\", \"SendType\": \"TMSG07\", \"PSID\": \"0x8002\", \"Channel\": \"183\" },{ \"TmxType\": \"TMSG03-P\", \"SendType\": \"TMSG03\", \"PSID\": \"0xBFEE\", \"Channel\": \"183\" },{ \"TmxType\": \"TMSG05-P\", \"SendType\": \"TMSG05\", \"PSID\": \"0x8003\", \"Channel\": \"183\" }, { \"TmxType\": \"SSM-P\", \"SendType\": \"SSM\", \"PSID\": \"0x8002\", \"Channel\": \"183\" },{ \"TmxType\": \"SDSM\", \"SendType\": \"SensorDataSharingMessage\", \"PSID\": \"0x8010\", \"Channel\": \"183\" }] }",
"default": "{ \"Messages\": [ { \"TmxType\": \"SPAT-P\", \"SendType\": \"SPAT\", \"PSID\": \"0x8002\", \"Channel\": \"183\" }, { \"TmxType\": \"MAP-P\", \"SendType\": \"MAP\", \"PSID\": \"0x8002\", \"Channel\": \"183\" }, { \"TmxType\": \"PSM-P\", \"SendType\": \"PSM\", \"PSID\": \"0x27\", \"Channel\": \"183\" }, { \"TmxType\": \"RSM\", \"SendType\": \"RSM\", \"PSID\": \"0x8003\", \"Channel\": \"183\" }, { \"TmxType\": \"TIM\", \"SendType\": \"TIM\", \"PSID\": \"0x8003\", \"Channel\": \"183\" }, { \"TmxType\": \"TMSG07-P\", \"SendType\": \"TMSG07\", \"PSID\": \"0x8002\", \"Channel\": \"183\" },{ \"TmxType\": \"TMSG03-P\", \"SendType\": \"TMSG03\", \"PSID\": \"0xBFEE\", \"Channel\": \"183\" },{ \"TmxType\": \"TMSG05-P\", \"SendType\": \"TMSG05\", \"PSID\": \"0x8003\", \"Channel\": \"183\" }, { \"TmxType\": \"SSM-P\", \"SendType\": \"SSM\", \"PSID\": \"0x8002\", \"Channel\": \"183\" },{ \"TmxType\": \"SDSM\", \"SendType\": \"SensorDataSharingMessage\", \"PSID\": \"0x8010\", \"Channel\": \"183\" }] }",
"description": "JSON data defining the message types, PSIDs, and channel number for messages forwarded to the V2X radio at destination 1."
},
{
Expand Down
35 changes: 35 additions & 0 deletions src/v2i-hub/RsmPlugin/CMakeLists.txt
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)
38 changes: 38 additions & 0 deletions src/v2i-hub/RsmPlugin/manifest.json
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."
}

]
}
232 changes: 232 additions & 0 deletions src/v2i-hub/RsmPlugin/src/RsmPlugin.cpp
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);
}
15 changes: 15 additions & 0 deletions src/v2i-hub/RsmPlugin/src/RsmPluginWorker.cpp
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 {

};
Loading

0 comments on commit 0dad656

Please sign in to comment.